C語言實現三子棋遊戲(意義版)
我還會再遇到ta。
所以,這並不算是真正意義上得離別。
雖然從近幾個月幾乎每天都跟ta走的頗近。每次得相遇都會讓我恍惚。
我想躲著ta的一些,但是每次提起思緒卻總會跟ta不期而遇。
遇時苦惱,別時著迷。
昨日又與ta相遇,這一聚,就是六個多時辰。從正午窗外得鳴笛到回頭時到卷閘門刺耳的伸展,我才想起跟一碗炸醬麵不見不散得約定。
跟後者比起來,離別帶給我的,更是精神食糧。
好了ta就是BUG
實現了三子棋後,這一離別才顯得更有意義。理解和實現差之千里,程式設計就是這樣。對於實現入門三子棋可能是大同小異的,但是我在內部加入了標籤,讓這個小程式變得更加意義深刻,同時一記與BUG的不解之緣。
實現:
首先應該想到使用函式來使分工簡潔明確
選單,遊戲功能。
選單:
main函式中設定menu()函式來列印選單 即 開始遊戲和退出遊戲,使用do while語句來呼叫遊戲功能game()函式。實現完整的互動。
對於遊戲內部功能game()而言,設定
1 初始化棋盤 (空格和外觀)2 列印棋盤 (每次下棋後進行結果顯示)3 使用者下棋 4 電腦隨機下棋
5 輸贏判斷 6 平局判斷
這麼多函式都放在一個原始檔顯然是酸辣的,所以我們定義一個實現遊戲的標頭檔案”threechess.h“進行函式的宣告,後編寫定義他們的原始檔”threechess.c".
第一步:先在main函式中講函式流程實現
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include"threechess.h" #include<Windows.h> #include<time.h> void menu() { printf("*******************************************\n"); printf("------ 我可以大口吞下玻璃而不傷身體--------\n"); //label 1. original test. printf("------1. 開始遊戲-------------------------\n"); printf("------0. 退出遊戲-------------------------\n"); printf("*******************************************\n"); };void game(); int main() { menu(); int a = 0; do { assert(scanf("%d", &a));//防止使用者輸入非整型十進位制數字 switch (a) { case 1: game(); menu(); break; case 0: return 0; default: printf("輸入錯誤"); } } while (a); }
threechess.h
第二步 編寫遊戲功能的標頭檔案
#pragma once #define ROW 3 #define COL 3 voidinitboard(char arr[ROW][COL], int row, int col);//初始化棋盤 //列印棋盤 void display(char arr[ROW][COL], int row, int col); //人走棋 void playermove(char arr[ROW][COL], int row, int col); //機器走 void automove(char arr[ROW][COL], int row, int col); //判斷輸贏 int JUDGE(char arr[ROW][COL], int row, int col); //平局情況 int FULL(char arr[ROW][COL], int row, int col);
threechess.c
第三步在該原始檔中定義功能
#include "threechess.h"
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void initboard(char arr[ROW][COL], int row, int col)//此處第一個引數是指產生二維指標,不能夠省略第一個下標符第二個下標符和值
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = ' '; //將內容初始化
}
}
}
void display(char arr[ROW][COL], int row, int col)//顯示棋盤
{
int i = 0;
int j = 0;
printf("-------------\n");
for (i = 0; i < row; i++)
{
printf("|");
for (j = 0; j < col; j++)
{
printf(" %-2c|", arr[i][j]);
}
if (row - 2 == i)
{
(printf(" ***幫幫烏干達得可憐兒童!***")); // label 2.VIM version
}
printf("\n-------------\n");// 目的在於每行列印完了以後再下面加上柵;
}
}
void playermove(char arr[ROW][COL], int row, int col) //玩家移動
{
while (1)
{
int x = 0, y = 0;
assert(scanf("%d%d", &x, &y));//此處強調,如果用使用者輸入的值非十進位制整型,比如%……&*&*!@#asdvc字元型,那麼scanf函式將不進行匹配,返回匹配成功的專案數,用assert斷言函式來進行判斷
x--;//因為使用者輸入得值位陣列下表加一所以在這裡--
y--;
if ((x >= 0 && x < row) && (y >= 0 && y < col))//防止越界
{
if (' ' == arr[x][y])
{
arr[x][y] = '*';
break;
}
else
{
printf("\n此位置已放置\n");
}
}
else
{
printf("\n你飄了\n"); //沒放好就是飄了
}
}
}
void automove(char arr[ROW][COL], int row, int col)//電腦移動
{
srand((unsigned)time(NULL)); //設定隨機起點
while (1)
{
int x = rand() % 3; //使隨機值在0-2
int y = rand() % 3;
if (' ' == arr[x][y]) //防止重疊
{
arr[x][y] = 'X';
break;
}
}
}
int JUDGE(char arr[ROW][COL], int row, int col) //判斷
{
int i = 0;
for (i = 0; i < ROW; i++)//判斷列
{
if (arr[i][COL - 1] == arr[i][COL - 2] && arr[i][COL - 2] == arr[i][COL - 3]) //此處當下標時 數值要-1 很關鍵!
{
if (arr[i][COL - 1] != ' ')
{
return arr[i][COL - 1];
}
}
}
for (i = 0; i < COL; i++) //判斷行
{
if (arr[ROW - 1][i] == arr[ROW - 2][i] && arr[ROW - 2][i] == arr[ROW - 3][i])
{
if (arr[ROW - 1][i] != ' ')
{
return arr[ROW - 1][i];
}
}
}
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2]) //判斷斜行
{
if (arr[0][0] != ' ')
{
return arr[0][0]; //返回複合條件的字元
}
}
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0])//判斷對稱斜行
{
if (arr[0][2] != ' ')
{
return arr[0][2]; //返回複合條件的字元
}
}
if (FULL(arr, row, col) == 0) //在judge中引用FULL函式進行平局判斷
{
return 'd';//返回複合條件的字元
}
return 0; //沒有返回0
}
int FULL(char arr[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (' ' == arr[i][j])
{
return 1; //供judge判斷
}
}
}
return 0;
}
第四步,game()功能實現
void game() { char arr[ROW][COL] = { 0 }; initboard(arr, ROW, COL); display(arr, ROW, COL); while (1) { playermove(arr, ROW, COL); //玩家操作 display(arr, ROW, COL);//將結果顯示 if (JUDGE(arr, ROW, COL) != 0)//判斷是否產生結果 { break; } automove(arr, ROW, COL); //電腦操作 display(arr, ROW, COL);//顯示結果 if (JUDGE(arr, ROW, COL) != 0)//判斷 { break; } } if (JUDGE(arr, ROW, COL) =='d' )//結束後檢測是否複合平局判斷 { printf("你勉強合格");//輸出平局結果 } else if (JUDGE(arr, ROW, COL) == 'X')//電腦勝出結果判斷 { printf("出門左轉上336\n"); } else if (JUDGE(arr, ROW, COL) == '*')//玩家結果判斷 { printf("THAT'S VERY KIND OF YOU!\n"); } return 0;}
輸出結果
1.介面
1.電腦贏
2.玩家贏
**對於label 1與2
1.來字linux系統經典字型測試
2.來自vim的歡迎語
顯得更有意義。
**關於scanf的返回值,scanf返回的是正確入讀的專案數,即(%d%d%d,&a,&b)它的返回值也是3,但是如果第一個專案未提取成功,那麼即使後面是正確的型別,返回值也是0