【C语言】C语言系列—五子棋的实现
一个五子棋程序,可以分为四个部分,第一部分是头文件的创立,它可以让我们的函数很好的封装起来,其中有两个细节需要注意:一是在头文件中用define定义行和列,这样我们将来要对行和列进行改动的时候只用改define这一个地方。二是把stdio.h time.h 等头文件包含在game.h 这个头文件中,避免重复包含。
第二部分是test.c函数逻辑的实现,它包含了实现这个游戏所需要的基本逻辑,包括菜单的打印、棋盘的初始化、棋盘的打印、玩家和电脑下棋、游戏状态的判断。
第三部分是游戏相关函数的实现,前面是对游戏各个具体功能的阐述,后面是总的代码。
第四部分是游戏效果展示。
第五部分:游戏总体实现代码
第一部分:
头文件的内容--游戏相关函数的声明、符号的声明、头文件的包含
#pragma once//game.h 游戏相关函数的声明、符号的声明、头文件的包含//符号的声明#define ROW 5#define COL 5//头文件的包含#include#include#include//函数的声明//初始化棋盘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);//判断输赢//游戏状态:*:玩家赢// #:电脑赢// Q:平局// C:游戏继续char IsWin(char board[ROW][COL], int row, int col);
第二部分--测绘游戏的逻辑 test.c
#define _CRT_SECURE_NO_WARNINGS 1//test.c 测绘游戏的逻辑//game.c 游戏相关函数的实现//game.h 游戏相关函数的声明、符号的声明、头文件的包含#define _CRT_SECURE_NO_WARNINGS 1 //解决VS中scanf不安全问题#include"game.h"//自己创建的头文件用双引号void menu() //菜单的实现{printf("1.play\n");printf("0.exit\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 != '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");elseprintf("平局\n");}int main(){int n = 0;srand((unsigned int)time(NULL));do {menu();printf("请选择:->");scanf("%d", &n);switch (n){case 1:game(); break;case 0:printf("退出游戏"); break;default:printf("选择错误,重新选择\n");}} while (n);return 0;}
第三部分--游戏相关函数的实现 game.c
1,棋盘初始化(实质是数组初始化)
//初始化棋盘void InitBoard(char board[ROW][COL], int row, int col){int i = 0, j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++)board[i][j] = ' '; //将棋盘初始化为空格}}
2,打印棋盘
//打印棋盘void DisplayBoard(char board[ROW][COL], int row, int col){int i = 0, 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,玩家下棋--其中要判断玩家输入的坐标是否合法以及该坐标是否被占用
//玩家下棋void PlayerMove(char board[ROW][COL], int row, int col){int m = 0, n = 0;printf("玩家走\n");while (1)//如果坐标违法就重新输入{printf("请输入坐标->:");scanf("%d%d", &m, &n);//判断坐标合法性if (m = 1 && n = 1){//判断坐标是否被占用if (board[m - 1][n - 1] == ' ') //玩家不知道数组下标从零开始,输入是从(1 1)开始的,所以要减一{board[m - 1][n - 1] = '*';break;}elseprintf("坐标被占用,请重新输入\n");}elseprintf("坐标非法,请重新输入\n");}}
4,电脑下棋--要让电脑产生一个在数组范围内的随机坐标,要用到随机函数值产生函数rand(),同时为保证该值的随机性,需要为其设置一个种子,同时要判断坐标是否被占用。
//电脑下棋void ComputerMove(char board[ROW][COL], int row, int col){int m = 0, n = 0;printf("电脑走\n");while (1){m = rand() % row;n = rand() % col;//判断坐标是否被占用if (board[m][n] == ' '){board[m][n] = '#';break;}}}
5,判断游戏的状态--:*:玩家赢
#:电脑赢
Q:平局
C:游戏继续
//判断输赢char IsWin(char board[ROW][COL], int row, int col){int i = 0, j = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1]&& board[i][1] == board[i][2]&& board[i][2] == board[i][3]&& board[i][3] == board[i][4]&& board[i][4] != ' ')return board[i][1];}for (i = 0; i < col; i++){if (board[0][i] == board[1][i]&& board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[2][i] == board[3][i]&& board[3][i] == board[4][i]&& board[4][i] != ' ')return board[1][i];}if (board[0][0] == board[1][1]&& board[1][1] == board[2][2]&& board[2][2] == board[3][3]&& board[3][3] == board[4][4]&& board[4][4] != ' ')return board[0][0];if (board[0][4] == board[1][1]&& board[1][1] == board[2][2]&& board[2][2] == board[3][3]&& board[3][3] == board[4][4]&& board[4][4] != ' ')return board[0][0];int ret = IsFull(board, row, col);if (ret)return 'Q';return 'C';}
6,判断游戏状态--判断棋盘是否下满
in//判断棋盘是否满了int IsFull(char board[ROW][COL], int row, int col){int i = 0, j = 0, flag = 1;for (i = 0; i < row; i++){for (j = 0; j < col; j++)if (board[i][j] == ' ')flag = 0;}return flag;}
7,game.c 的总体实现
#define _CRT_SECURE_NO_WARNINGS 1//game.c 游戏相关函数的实现#include"game.h"//初始化棋盘void InitBoard(char board[ROW][COL], int row, int col){int i = 0, 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, 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 :");scanf("%d%d", &m, &n);//判断坐标合法性if (m = 1 && n = 1){//判断坐标是否被占用if (board[m - 1][n - 1] == ' ') //玩家不知道数组下标从零开始,输入是从(1 1)开始的,所以要减一{board[m - 1][n - 1] = '*';break;}elseprintf("坐标被占用,请重新输入\n");}elseprintf("坐标非法,请重新输入\n");}}//电脑下棋void ComputerMove(char board[ROW][COL], int row, int col){int m = 0, n = 0;printf("电脑走\n");while (1){m = rand() % row;n = rand() % col;//判断坐标是否被占用if (board[m][n] == ' '){board[m][n] = '#';break;}}}//判断棋盘是否满了int IsFull(char board[ROW][COL], int row, int col){int i = 0, j = 0, flag = 1;for (i = 0; i < row; i++){for (j = 0; j < col; j++)if (board[i][j] == ' ')flag = 0;}return flag;}//判断输赢char IsWin(char board[ROW][COL], int row, int col){int i = 0, j = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1]&& board[i][1] == board[i][2]&& board[i][2] == board[i][3]&& board[i][3] == board[i][4]&& board[i][4] != ' ')return board[i][1];}for (i = 0; i < col; i++){if (board[0][i] == board[1][i]&& board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[2][i] == board[3][i]&& board[3][i] == board[4][i]&& board[4][i] != ' ')return board[1][i];}if (board[0][0] == board[1][1]&& board[1][1] == board[2][2]&& board[2][2] == board[3][3]&& board[3][3] == board[4][4]&& board[4][4] != ' ')return board[0][0];if (board[0][4] == board[1][1]&& board[1][1] == board[2][2]&& board[2][2] == board[3][3]&& board[3][3] == board[4][4]&& board[4][4] != ' ')return board[0][0];int ret = IsFull(board, row, col);if (ret)return 'Q';return 'C';}
第四部分--游戏效果
1,菜单的效果
2,初始化棋盘的效果
3,游戏进行的效果
4,游戏结束的效果
第五部分:游戏总体实现代码。
game.h
#pragma once//game.h 游戏相关函数的声明、符号的声明、头文件的包含//符号的声明#define ROW 5#define COL 5//头文件的包含#include#include#include//函数的声明//初始化棋盘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);//判断输赢//游戏状态:*:玩家赢// #:电脑赢// Q:平局// C:游戏继续char IsWin(char board[ROW][COL], int row, int col);
test.c
#define _CRT_SECURE_NO_WARNINGS 1//test.c 测绘游戏的逻辑//game.c 游戏相关函数的实现//game.h 游戏相关函数的声明、符号的声明、头文件的包含#define _CRT_SECURE_NO_WARNINGS 1 //解决VS中scanf不安全问题#include"game.h"//自己创建的头文件用双引号void menu() //菜单的实现{printf("1.play\n");printf("0.exit\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 != '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");elseprintf("平局\n");}int main(){int n = 0;srand((unsigned int)time(NULL));do {menu();printf("请选择:->");scanf("%d", &n);switch (n){case 1:game(); break;case 0:printf("退出游戏"); break;default:printf("选择错误,重新选择\n");}} while (n);return 0;}
game.c
#define _CRT_SECURE_NO_WARNINGS 1//game.c 游戏相关函数的实现#include"game.h"//初始化棋盘void InitBoard(char board[ROW][COL], int row, int col){int i = 0, 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, 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 :");scanf("%d%d", &m, &n);//判断坐标合法性if (m = 1 && n = 1){//判断坐标是否被占用if (board[m - 1][n - 1] == ' ') //玩家不知道数组下标从零开始,输入是从(1 1)开始的,所以要减一{board[m - 1][n - 1] = '*';break;}elseprintf("坐标被占用,请重新输入\n");}elseprintf("坐标非法,请重新输入\n");}}//电脑下棋void ComputerMove(char board[ROW][COL], int row, int col){int m = 0, n = 0;printf("电脑走\n");while (1){m = rand() % row;n = rand() % col;//判断坐标是否被占用if (board[m][n] == ' '){board[m][n] = '#';break;}}}//判断棋盘是否满了int IsFull(char board[ROW][COL], int row, int col){int i = 0, j = 0, flag = 1;for (i = 0; i < row; i++){for (j = 0; j < col; j++)if (board[i][j] == ' ')flag = 0;}return flag;}//判断输赢char IsWin(char board[ROW][COL], int row, int col){int i = 0, j = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1]&& board[i][1] == board[i][2]&& board[i][2] == board[i][3]&& board[i][3] == board[i][4]&& board[i][4] != ' ')return board[i][1];}for (i = 0; i < col; i++){if (board[0][i] == board[1][i]&& board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[2][i] == board[3][i]&& board[3][i] == board[4][i]&& board[4][i] != ' ')return board[1][i];}if (board[0][0] == board[1][1]&& board[1][1] == board[2][2]&& board[2][2] == board[3][3]&& board[3][3] == board[4][4]&& board[4][4] != ' ')return board[0][0];if (board[0][4] == board[1][1]&& board[1][1] == board[2][2]&& board[2][2] == board[3][3]&& board[3][3] == board[4][4]&& board[4][4] != ' ')return board[0][0];int ret = IsFull(board, row, col);if (ret)return 'Q';return 'C';}