今天我给大家带来一个小游戏,三子棋的简单实现。跟着本篇文章,你也可以做出属于你自己的三子棋。
游戏的整体思路
1.text.c————用来测试游戏
2.game.c————游戏功能的实现
3.game.h————游戏功能的声明
‘*’代表着玩家下的棋(也表示赢),‘#’代表电脑下的棋(也表示赢),‘Q’表示和棋,‘C’表示继续,
text.c————我们用来测试游戏,我们玩游戏时都会先玩一把,所以我们会选择用do while的循环来解决,当我们第一次进入时,就应该有一个菜单来问我们是否玩游戏,这就用到了我们的menu函数,然后我们可以根据我们选择来选择是否玩游戏。
int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出成功\n"); break; default: printf("选择错误,重新选择:>\n"); break; } } while (input); return 0; }
我们定义了一个int类型的临时变量input,然后我们根据input的不同来选择是否进行游戏,当我们选择1时,我们就玩游戏,选择0时就选择退出游戏,如果不是这2个数就重新选择。
这是我们来实现menu函数,我们只需要打印菜单就行,所以我们不需要传参和返回值,直接printf就可以了
void menu() { printf("*************************\n"); printf("******** 1.play *******\n"); printf("******** 0.exit *******\n"); printf("*************************\n"); }
- 这样一看,我们就完成了菜单的打印。当我们选择1时,我们就进入了switch的选择,进入了game函数。
void game() { char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); char ret = 0; while (1) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; //电脑下 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') printf("玩家赢\n"); else if (ret == '#') printf("电脑赢\n"); else printf("和局\n"); }
我们先定义一个3行3列的二维数组,为了我们代码的可读性,我们就可以将行改为ROW,列对应为COL,这是我们就可以在game.h中#define了
- game. h
#pragma once #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 3 #define COL 3
game.h中,我们是把库函数都放在了game.h中,然后我们用#define定义了一下ROW ,COL的数,这样当我们想把棋盘改为5x5的时候,只需要改变game.h的值就可以实现所有的改变。
回到text.c中,我们定义完char类型的二维数组,我们就要初始化它,将二维数组全部初始化为‘ ’。 这时我们就需要在game.h中声明一下InitBoard的函数,将我们的二维数组、行、列全部传进去。
game.h中我们就可以这样声明
void InitBoard(char board[ROW][COL], int row,int col);
然后我们函数的实现就让在了game.c中,
void InitBoard(char board[ROW][COL],int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { board[i][j] = ' '; } } }
我们想,把棋盘初始化后,是不是要显示棋盘,我们就要用到我们的DisPlayBoard的函数,目标是实现这个图。
我们发现第一行是由空格和|组成的,我们row是3,然而我们最后一列没有|,我们就可以分别来实现它,而第二行就是___和|组成的,最后一列也是没有|。这时可以实现DisPlayBoard函数了,代码如下。
void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j <col - 1) { printf("|"); } } printf("\n"); for (j = 0; j < col; j++) { printf("---"); if (j < col - 1)//col-1 == 2 printf("|"); } printf("\n"); } }
当然,我们也要在game.h中声明这个函数,当我们实现完显示棋盘的函数,这时我们就可以来实现用户走的函数了,我们可以定义一个PlayerMove的函数,定义一个电脑移动的函数(ComputerMove),我们在game.h中声明一下,然后就可以在game.c中实现了
void PlayerMove(char board[ROW][COL], int row, int col) { int pos_x = 0; int pos_y = 0; printf("玩家输入:>"); while (1) { printf("请输入棋盘坐标\n"); scanf("%d %d", &pos_x, &pos_y); if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col) { if (board[pos_x-1][pos_y-1] == ' ') { board[pos_x-1][pos_y-1] = '*'; break; } else { printf("pos is occupied\n"); } } else { printf("pos is error\n"); } } }
我们定义pos_x和pos_y来表示要走的位置,我们落的棋子就必须在棋盘中,这就有了第一个if的判断,第二个if判断中如果落得那个位置是‘ ’,就代表了那个位置没有人下,我们就可以把“*”下在那个位置,然后挑出循环,如果下的位置有人落了,我们就要重新下,循环一下就可以实现了。但请注意,我下的位置是[pos_x-1][pos_y],这是因为我们的数组下标是从0开始的,而用户玩的时候,以为的1行1列就是我们的0行0列,所以我们都要-1,。
void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑输入:>\n"); while (1) { int pos_x = rand() % row;//0-row-1 int pos_y = rand() % col;//0-col-1 if (board[pos_x][pos_y] == ' ') board[pos_x][pos_y] = '#'; break; } }
电脑下的棋子当然要下在棋盘内,所以我们用到了%row,表示着0-row-1的位置,我们要在棋盘内随机落子,我们就要用到rand函数,rand函数就要用到srand函数,我们可以把srand放在main函数中,
srand(((unsigned int)time(NULL)));
这个代表着时间戳,我们显示生活中的时间都是一直在走的,这样我们就可以实现随机落子了,我们用srand函数中用到了time的类型我们就把它置位空,类型强转为(unsigned int),注意,我们的srand要把它放在while函数之前,不能放在while函数中,我们可以这样理解,如果我们把srand函数放在whlie函数中,我们是不是每次循环的时候,时间都要重新设定一下,这样就不符合我们的定义了。
然后就是我们的IsWin函数了,我们把board,row,col传参传过去,我们要实现IsWin函数,老方法需要我们在game.h中声明一下,在game.c中实现函数
char IsWin(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][0];//返回谁赢 '*' '#' 'Q' 'C' } for (i = 0; i < row; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] &&board[0][i] != ' ') return board[0][i]; } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] &&board[1][1] != ' ') return board[i][i]; if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') return board[1][1]; if ((IsFull(board, row, col)) == 1) return 'Q'; return 'C'; }
我们定义一个int类型的变零i,然后我们用for循环,进入第一个if判断,如果连着3个都相等,而且都不等于‘ ’,我们就可以返回board【i】【0】,代表着谁连3个就谁赢,第二个if判断就是判断列是否相等,第三个和第四个是判断斜对角是否3个连着的。
- 当棋盘满了的时候,我们就返回了‘Q’,代表着和棋,如果上述三个都不满足,就表示继续下棋。
- IsFull函数需要我们遍历一下,用for循环,代码如下,
int IsFull(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (board[i][j] == ' ') return 0; } } //返回为1 if才会进去 return 1; }
- 如果我们的3行3列棋盘都没有‘ ’的时候就代表着满了返回1,如果有一个等于‘ ’,我们就返回0,我们的IsFull函数就根据我们返回值来判断棋盘是否为空。
- 最后,附上game.c的代码
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //初始化棋盘为空格 void InitBoard(char board[ROW][COL],int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; 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++) { int j = 0; for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j <col - 1) { printf("|"); } } printf("\n"); for (j = 0; j < col; j++) { printf("---"); if (j < col - 1)//col-1 == 2 printf("|"); } printf("\n"); } } void PlayerMove(char board[ROW][COL], int row, int col) { int pos_x = 0; int pos_y = 0; printf("玩家输入:>"); while (1) { printf("请输入棋盘坐标\n"); scanf("%d %d", &pos_x, &pos_y); if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col) { if (board[pos_x-1][pos_y-1] == ' ') { board[pos_x-1][pos_y-1] = '*'; break; } else { printf("pos is occupied\n"); } } else { printf("pos is error\n"); } } } int IsFull(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (board[i][j] == ' ') return 0; } } //返回为1 if才会进去 return 1; } void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑输入:>\n"); while (1) { int pos_x = rand() % row;//0-row-1 int pos_y = rand() % col;//0-col-1 if (board[pos_x][pos_y] == ' ') board[pos_x][pos_y] = '#'; break; } } char IsWin(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][0];//返回谁赢 '*' '#' 'Q' 'C' } for (i = 0; i < row; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] &&board[0][i] != ' ') return board[0][i]; } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] &&board[1][1] != ' ') return board[i][i]; if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') return board[1][1]; if ((IsFull(board, row, col)) == 1) return 'Q'; return 'C'; }
- 如果我们的3行3列棋盘都没有‘ ’的时候就代表着满了返回1,如果有一个等于‘ ’,我们就返回0,我们的IsFull函数就根据我们返回值来判断棋盘是否为空。
- 最后,附上game.c的代码
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //初始化棋盘为空格 void InitBoard(char board[ROW][COL],int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; 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++) { int j = 0; for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j <col - 1) { printf("|"); } } printf("\n"); for (j = 0; j < col; j++) { printf("---"); if (j < col - 1)//col-1 == 2 printf("|"); } printf("\n"); } } void PlayerMove(char board[ROW][COL], int row, int col) { int pos_x = 0; int pos_y = 0; printf("玩家输入:>"); while (1) { printf("请输入棋盘坐标\n"); scanf("%d %d", &pos_x, &pos_y); if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col) { if (board[pos_x-1][pos_y-1] == ' ') { board[pos_x-1][pos_y-1] = '*'; break; } else { printf("pos is occupied\n"); } } else { printf("pos is error\n"); } } } int IsFull(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (board[i][j] == ' ') return 0; } } //返回为1 if才会进去 return 1; } void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑输入:>\n"); while (1) { int pos_x = rand() % row;//0-row-1 int pos_y = rand() % col;//0-col-1 if (board[pos_x][pos_y] == ' ') board[pos_x][pos_y] = '#'; break; } } char IsWin(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][0];//返回谁赢 '*' '#' 'Q' 'C' } for (i = 0; i < row; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] &&board[0][i] != ' ') return board[0][i]; } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] &&board[1][1] != ' ') return board[i][i]; if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') return board[1][1]; if ((IsFull(board, row, col)) == 1) return 'Q'; return 'C'; }
- game.h的代码
#pragma once #include <stdio.h> #include <stdlib.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 PlayerMove(char board[ROW][COL], int row, int col); void ComputerMove(char board[ROW][COL], int row, int col); char IsWin(char board[ROW][COL], int row, int col);
- text.c的代码
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void menu() { printf("*************************\n"); printf("******** 1.play *******\n"); printf("******** 0.exit *******\n"); printf("*************************\n"); } void game() { char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL); char ret = 0; while (1) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; //电脑下 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') printf("玩家赢\n"); else if (ret == '#') printf("电脑赢\n"); else printf("和局\n"); } int main() { int input = 0; srand(((unsigned int)time(NULL))); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出成功\n"); break; default: printf("选择错误,重新选择:>\n"); break; } } while (input); return 0; }
最后:这样我们就实现了简单的三子棋,当然我们也有问题,当我们的棋盘变成10x10时,我们IsWin的判断就有问题了,我们也只能判断3子棋,如果有兴趣,可以适当改一下代码,让它变成多子棋。