通過對陣列,函式,回圈知識的應用我們可以獨立地創建一個專案--三子棋,首先我們對于三子棋的實作要有一個大概的思路和邏輯,
檔案的創建
工欲善其事必先利其器,為了更好地完成專案,先創建三個檔案--兩個源檔案,一個頭檔案,測驗檔案-test.c,游戲檔案game.c,游戲頭檔案game.h,游戲檔案主要就是存放與游戲程序實作有關代碼,例如:初始化函式,列印棋盤函式等;測驗檔案主要就是存放main函式和一些輔助實作的函式;游戲頭檔案里就是游戲檔案中函式的宣告,做頭檔案被測驗檔案引入,
先在test.c中把主函式寫一寫:
int main()
{
test();
return 0;
}
//將測驗單獨寫成一個函式,分塊處理,使邏輯更加清晰
再把test函式寫一寫,當程式運行到test函式時,就已經進入到游戲的初始界面啦,
#include<stdio.h>
void menu()
{
printf("---------------------\n");
printf("------1.play---------\n");
printf("------0.exit---------\n");
printf("---------------------\n");
}
void test()
{
int input = 0;//用到的變數最好在函式前面引入,不要在復合陳述句中引入,
//這樣它的作用域就小了,復合陳述句外再想用這個變數就無法使用了,
do
{
menu();
printf("請選擇:");
scanf("%d",&input);
switch (input)
{
case 1:
game();
break;
case 0: //因為游戲玩一次常常玩不夠,所以選擇的是回圈結構
printf("離開游戲\n");
break;
default:
printf("輸入錯誤請重新輸入");
break;
}
}while(input);
}
int main()
{
test();
return 0;
}
大體思路
1.下的棋子也算是資料,資料要存盤在哪里?
2.要先初始化棋盤,并且列印出來,看看初始的棋盤是怎樣的,
3.游戲開始,玩家下一步,電腦下一步,要清楚這是一個有條件的回圈程序,
4.判斷輸贏,判斷輸贏的根據又是什么?
在game()的函式中寫下思路
void game()
{
char board[3][3] = {0};//初始化一個陣列用來存放資料
//初始化棋盤;
//列印棋盤;
//游戲開始:玩家走,電腦走,回圈的程序,
//判斷輸贏,
}
為了使程式更具改造性,在game.h中宏定義,之后就用字串來表示數字,以后需要改成五子棋,十字棋等等,只需要在頭檔案這里修改3為5,10就好了,
#define ROW 3
#define COL 3
void game()
{
char board[3][3] = {0};//初始化一個陣列用來存放資料
//初始化棋盤;
//列印棋盤;
//游戲開始:玩家走,電腦走,回圈的程序,
//判斷輸贏,
}
1.資料的儲存
三子棋--三行三列,這樣的資料一定是被存盤在一組二維陣列中的,并且是字符型別的陣列中,
2.初始化棋盤,列印棋盤
初始化棋盤,在沒有下棋的時候,每個棋點都應該是空格,在游戲檔案下寫一個陣列初始化的函式
//寫在game.c內
//初始化棋盤
void Initboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
列印棋盤,列印棋盤就要知道棋盤是什么樣子的,
大概就是這個樣子,照葫蘆畫瓢,代碼誕生:
void Displayboard(char board[ROW][COL], int row, int col)
{
int i = 0;
for(i = 0; i < row; i++)
{
//列印資料
printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2] );
//列印分割行
if(i < col -1)
printf("___|___|___\n");
}
}
但是這個代碼明顯有局限性,就是只能列印三列,比如說某一天突然要來個五子棋,十字棋,那還要重新修改這段代碼,而且被修改這段代碼又長,現在對個代碼進行優化:
void Displayboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for(i = 0; i < row; i++)
{
//列印資料
for(j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if ( j < col - 1)
printf("|");
}
//換行
printf("\n");
//列印分割行
if( i < row - 1)
{
for( j = 0; j < col; j++)
{
printf("___");
if( j < col - 1)
printf("|");
}
}
//換行
printf("\n");
}
}
這樣一個棋盤的初始化函式和列印函式就完成了,
3.游戲開始
游戲的程序無非就是玩家下棋,電腦下棋,就寫兩個函式,一個是玩家下棋的函式,一個是電腦下棋的函式,還是在game.c的檔案下寫,
void Player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋>");
int x = 0;
int y = 0;
scanf("%d %d",&x,&y);
while (1)
{
if( x >= 1 && x <= row && y >= 1 && y <= col)
{
if( board[x - 1][y - 1] ==' ')
{
board [x - 1][y - 1] = '*';//玩家下棋用'*'
break;
}
else
{
printf("該坐標被占用 請重新選擇\n");
}
}
else
{
printf("輸入錯誤,請重新輸入\n");
}
}
}
void Computer_move(char board[ROW][COL], int row, int col)
{
int x = rand() % 3;//隨機生成數字,取3的余數,總是0~2
int y = rand() % 3;
while (1)
{
if( board[x][y] ==' ')
{
board[x][y] = '#';//電腦下棋用'#'
break;
}
}
}
這些代碼看起來好像都沒有錯,但是,卻跑不起來!因為電腦下棋的函式,隨機生成的x,y進入到函式中就是固定的了!不符合條件的話一直回圈!無法跳出,所以隨機生成的數應該在回圈內部,
void Computer_move(char board[ROW][COL], int row, int col)
{
while (1)
{
int x = rand() % 3;//隨機生成數字,取3的余數,總是0~2
int y = rand() % 3;
if( board[x][y] ==' ')
{
board[x][y] = '#';//電腦下棋用'#'
break;
}
}
}
4.判斷輸贏
最后再寫一個函式判斷輸贏,如果玩家贏了回傳'*',如果電腦贏了回傳'#',如果平局回傳'p',如果游戲還在繼續就回傳'c',
int is_full(char board[ROW][COL],int row, int col)
{
int n = 0;
int m = 0;
for ( n = 0; n < row; n++)
{
for ( m = 0; m < col; m++)
{
if ( board[n][m] == ' ')
{
return 0;
}
}
}
return 1;
}
char is_win( char board[ROW][COL],int row, int col)
{
int i = 0;
//判斷行是否有3個相同的棋子
for (i = 0; i < row; i++)
{
if( board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] !=' ')
{
return board[i][1];
}
}
//判斷列是否為3個相同的棋子
for (i = 0; i < col; i++)
{
if( board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] !=' ')
{
return board[1][i];
}
}
//判斷對角線是否有三個相同的棋子
for(i = 0; i < col; i++)
{
if( board[0][0] == board[1][1] && board[1][1] ==board[2][2] && board[1][1] != ' ')
return board[1][1];
if( board[2][0] == board[1][1] && board[1][1] ==board[0][2] && board[1][1] != ' ')
return board[1][1];
//判斷是否平局
if (1 == is_full())
return 'p';
return 'c';
}
判斷輸贏的函式就大功告成了,
5.完善游戲函式
所有要被使用的函式都已經寫好,最后就該組裝這些函式了,主要就是添加在test.c下的game()函式中,在此之前,應該把所有用到的函式都在game.h中宣告一下,然后test.c檔案引入game.h頭檔案,這樣游戲里面的函式才能被正常呼叫,
//game.h下的全部代碼
#include<stdio.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化棋盤
void Initboard(char board[ROW][COL], int row, int col);
//列印棋盤
void Displayboard(char board[ROW][COL], int row, int col);
//玩家下棋
void Player_move(char board[ROW][COL], int row, int col);
//電腦下棋
void Computer_move(char board[ROW][COL], int row, int col);
//判斷是否獲勝
char is_win(char board[ROW][COL], int row, int col);
void game()
{
char board[3][3] = {0};//初始化一個陣列用來存放資料
//初始化棋盤
Initboard(board,ROW,COL);
//列印棋盤
Displayboard(board,ROW,COL);
//游戲開始
while(1)
{
//玩家走
Player_move(board,ROW,COL);
Displayboard(board,ROW,COL);
if ( is_win(board,ROW,COL) != 'c')
break;
//電腦走
Computer_move(board,ROW,COL);
Displayboard(board,ROW,COL);
if ( is_win(board,ROW,COL) != 'c')
break;
}
//判斷輸贏
if ( is_win(board) == '*' )
printf("玩家獲勝");
if ( is_win(board) == '#' )
printf("電腦獲勝");
if ( is_win(board) == 'p' )
printf("平局");
}
game()函式被完善好了!
6.完整代碼
//game.h下的全部代碼
#include<stdio.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化棋盤
void Initboard(char board[ROW][COL], int row, int col);
//列印棋盤
void Displayboard(char board[ROW][COL], int row, int col);
//玩家下棋
void Player_move(char board[ROW][COL], int row, int col);
//電腦下棋
void Computer_move(char board[ROW][COL], int row, int col);
//判斷是否獲勝
char is_win(char board[ROW][COL], int row, int col);
//test.c下的全部代碼
#include"game.h"
void game()
{
char ret;
//資料存盤到一個字符的二維陣列中,玩家為’*‘,電腦為’#‘
char board[ROW][COL] = { 0 }; //初始應均為空格
Initboard(board,ROW,COL); //初始化棋盤
Displayboard(board, ROW, COL); //列印棋盤
while (1)
{
Player_move(board,ROW,COL);
Displayboard(board, ROW, COL); //列印棋盤
ret = is_win(board, ROW, COL);
if (ret != 'c')
break;
Computer_move(board, ROW, COL);
Displayboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'c')
break;
}
if (ret == '*')
{
printf("玩家勝\n");
}
if (ret == '#')
{
printf("電腦勝\n");
}
if (ret == 'p')
{
printf("平局\n");
}
}
void menu()
{
printf("---------------------\n");
printf("------1.play---------\n");
printf("------0.exit---------\n");
printf("---------------------\n");
}
void test()
{
srand((unsigned)time(NULL));
int input = 0;
do
{
menu();
printf("請選擇:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("離開游戲");
break;
default:
printf("輸入錯誤,請重新輸入");
break;
}
} while(input);
}
int main()
{
test();
return 0;
}
//game.c下的全部代碼
#include"game.h"
//初始化棋盤
void Initboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//展示棋盤
void Displayboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
//列印資料
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//列印分割行
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
//玩家走
void Player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋>");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("該坐標已被占用,請重新輸入\n");
}
else
{
printf("超出范圍!請重新輸入\n");
}
}
}
//電腦走
void Computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦走>\n");
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int is_full(char board[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 (board[i][j] == ' ')
return 0;
}
}
return 1;
}
//玩家勝回傳'*',電腦勝回傳'#',平局回傳'p',繼續回傳'c'
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
return board[i][1];
}
//列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
return board[1][i];
}
//對角線
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
return board[1][1];
//平局
if (1 == is_full(board, ROW, COL))
return 'p';
//繼續
return 'c';
}
運行一下看看效果:
基本上可以實作三子棋的功能,不過這里仍有不足,我們可不可以賦予電腦智能化呢?就是讓電腦有自己的思想,可以和我們進行pk,而不只是單純地隨機生成數字下棋,這些下去我們仍需要思考,在這里就不做過多的解釋了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/354776.html
標籤:其他
上一篇:人類馴服人工智障(三子棋)
下一篇:舌尖上的C——三子棋的慢烹細作
