前言
实现一个简易的三子棋游戏,玩家能够和电脑进行对战,分出高下。
一、整体流程
- 创建三个文件,test.c用来放测试三子棋功能,game.c里放置游戏各个功能的实现代码,game.h用来放置需要用到的所有头文件及函数的声明。
- 在test.c中写一个菜单打印函数,用来每次游戏时打印菜单。在主函数中实现选择进入游戏,退出游戏等功能。当选择进入游戏,游戏具体操作的代码放在一个game()函数中。
- 书写game()函数,创建一个棋盘,并且完成棋盘的初始化,打印棋盘,玩家下棋,电脑下棋,判断输赢等功能。将这些功能包装成函数放在game.c中,并在game.h中声明。
- 完善代码并测试功能,进行修改完善。
二、具体代码实现
1、制作游戏菜单
void menu() { printf("************************\n"); printf("******1 开始游戏 *******\n"); printf("******0 退出游戏 *******\n"); printf("************************\n"); }
2、制作出主函数框架
int main() { int input = 0; srand((unsigned int)time(NULL));//这里是后面电脑下棋需要用到的 do { menu(); printf("请输入你的选择>\n"); scanf("%d", &input);//输入选择 switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入非法,请重新输入\n"); break; } } while (input); return 0; }
3、接下来完善game()函数,将游戏各个功能写在game.c中。用二维数组放置棋盘,棋盘的行和列长度可以放在头文件中定义,方便整体的修改。
void game() { char board[ROW][COL] = { 0 };//棋盘 InitBoard(board, ROW, COL);//置空初始化棋盘 DisplayBoard(board, ROW, COL);//打印棋盘 char ret = ' '; while (1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'B') { break; } printf("---------------------\n"); //电脑下棋 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'B') { break; } }
代码中的一些属性会在后续具体函数的代码中出现
4、棋盘中的元素都为0,需要进行初始化
void InitBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { board[i][j] = ' ';//将数组中所有元素置为空格 } } }
5、将棋盘打印出来,加上一些线区分每个棋子位置
void DisplayBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j < col - 1) { printf("|"); } } printf("\n"); if (i < row - 1) { for (int j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } printf("\n"); } } }
6、实现玩家下棋的功能
void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) { printf("该你下了(以空格隔开):\n"); scanf("%d %d", &x, &y);//输入想要下的坐标(从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"); } } }
7、实现电脑下棋功能
void ComputerMove(char board[ROW][COL], int row, int col) { printf("轮到电脑了:\n"); while (1) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
~srand((unsigned int)time(NULL));已经在主函数中写上,利用时间戳返回一个随机数
~int x =rand() % row ;可以得到0 ~ row-1的随机数,整体加一便可得到1~row的随机数~对col也是一样
8、判断是否胜利
这里需要用到一个判断棋盘是否已满的函数
int IsFull(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } //如果一个空格都没有,走出了循环,说明已经满了 return 1; }
判断是否胜利,返回不同的字符,在game()函数中进行判断,得出谁获得胜利
该判断只适用于3*3棋盘的三子棋
char IsWin(char board[ROW][COL], int row, int col) { //行 for (int i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') { return board[i][0]; } } //列 for (int 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[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //平局 if (IsFull(board, row, col)) { return 'A'; } return 'B'; }
9、记得将需要的头文件函数等在game.h中进行声明,并在test.c中引用该头文件
以下是头文件中的内容
#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); int IsFull(char board[ROW][COL], int row, int col); char IsWin(char board[ROW][COL], int row, int col);
三、整体代码
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); int IsFull(char board[ROW][COL], int row, int col); char IsWin(char board[ROW][COL], int row, int col);
game.c
#include "game.h" //数组置空 void InitBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { board[i][j] = ' '; } } } //打印数组 void DisplayBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j < col - 1) { printf("|"); } } printf("\n"); if (i < row - 1) { for (int j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } printf("\n"); } } } //玩家下棋 void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) { printf("该你下了(以空格隔开):\n"); scanf("%d %d", &x, &y);//输入想要下的坐标(从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 ComputerMove(char board[ROW][COL], int row, int col) { printf("轮到电脑了:\n"); while (1) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } //判断是否满了 int IsFull(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } return 1; } //判断是否胜利 char IsWin(char board[ROW][COL], int row, int col) { //行 for (int i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ') { return board[i][0]; } } //列 for (int 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[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //平局 if (IsFull(board, row, col)) { return 'A'; } return 'B'; } #
test.c
#include "game.h" //游戏菜单 void menu() { printf("************************\n"); printf("******1 开始游戏 *******\n"); printf("******0 退出游戏 *******\n"); printf("************************\n"); } //三子棋游戏 void game() { char board[ROW][COL] = { 0 };//棋盘 InitBoard(board, ROW, COL);//置空 DisplayBoard(board, ROW, COL);//打印棋盘 char ret = ' '; while (1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'B') { break; } printf("---------------------\n"); //电脑下棋 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'B') { 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("请输入你的选择>\n"); scanf("%d", &input);//输入选择 switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入非法,请重新输入\n"); break; } } while (input); return 0; }
四、效果测试