利用C语言实现五子棋游戏
作者:罅隙-
本文实例为大家分享了C语言实现五子棋游戏的具体代码,供大家参考,具体内容如下
一、前言
本文将先介绍五子棋运行所需要的函数,最后串联成完整代码。
我们需要实现的功能有:1.菜单menu函数
2.初始化棋盘Initboard函数
3.显示棋盘Displayboard函数
4.实现人机、人人模式的选择
5.落子函数 playermove computermove
6.判断输赢ifwin函数
先来看看运行效果吧!
二、头文件
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include<time.h> #include<stdlib.h> #include<windows.h> #define ROW 10 //定义棋盘的宽 #define COL 10 //定义棋盘的长 //定义常量方便全局的修改 void Initboard(char board[ROW][COL], int row, int col); //初始化棋盘 void Displayboard(char board[ROW][COL], int row, int col); //展示棋盘 void Playermove_1(char board[ROW][COL], int row, int col,int*px,int *py); //玩家一下棋 void Playermove_2(char board[ROW][COL], int row, int col,int*px, int *py); //玩家二下棋 void computermove(char board[ROW][COL], int row, int col); //电脑下棋 void game1(char board[ROW][COL], int row, int col); //人机模式 void game2(char board[ROW][COL], int row, int col); //人人模式 int Ifwin(char board[ROW][COL], int row, int col, int x, int y); //判断输赢 int check_x(char board[ROW][COL], int row, int col, int x, int y); //判断竖直五子 int check_y(char board[ROW][COL], int row, int col, int x, int y); //判断水平五子 int check_xy_up(char board[ROW][COL], int row, int col, int x, int y); //判断斜上五子 int check_xy_down(char board[ROW][COL], int row, int col, int x, int y); //判断斜下五子
三、menu菜单函数
void menu() { //完成菜单的初始化 printf("***********************\n"); printf("***********************\n"); printf("*****1.play 0.exit****\n"); printf("***********************\n"); printf("***********************\n"); printf("请输入:"); }
很简单,就不多说了
四、初始化棋盘Initboard函数
初始化棋盘,为数组一一存入空格
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] = ' '; } } }
五、显示棋盘Displayboard函数
打印简单的方格线,并打印数据内容
void Displayboard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (j = 0; j < col; j++)//打印横向y坐标 { if (j == 0)//考虑到x轴所占的一格 { printf(" %d ", j + 1); } else { printf(" %d ", j + 1); } } printf("\n"); for (i = 0; i < row; i++)//打印数据 { for (j = 0; j < col; j++) { if (j == 0)//顺带打印竖向x坐标 { printf("%2d",i+1);//%md表示域宽为m printf(" %c ",board[i][j]); } else { printf(" %c ", board[i][j]); } if (j < col - 1) printf("|"); } printf("\n"); //打印分割行 if (i < row - 1) { for (j = 0; j < col; j++) { if (j == 0)//同样考虑到y轴 printf(" ---"); else printf("---"); if (j < col - 1) printf("|"); } printf("\n"); } } }
六、落子函数
玩家一落子——playermove_1
void Playermove_1(char board[ROW][COL], int row, int col, int *px, int*py)//ROW可以省,COL不行 { int x = *px; int y = *py; while (1) { if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入坐标的合法性 { if (board[x -1][y- 1] == ' ')//保证落子点为空 { board[x-1 ][y -1] = '*'; *px = x; *py = y;//如果开始xy输入不合法,则要对外部xy修改,所以选择传址操作 break; } else { printf("你不能在此处落子\n"); printf("玩家1落子,请重新输入x y坐标: "); scanf("%d%d", &x, &y); } } else { printf("输入坐标不合法\n"); printf("玩家落子,请重新输入x y坐标: "); scanf("%d%d", &x, &y); } } }
玩家2落子完全相同,就不赘叙了
电脑落子
void computermove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; //rand函数的使用需要srand函数的初始化,但srand不可以被重复调用,所以放在外部 while (1) { x = rand() % ROW; y = rand() % COL; if (board[x][y] == ' ')//x的范围在0~row-1,所以这里x不用-1了 { board[x][y] = '#'; break; } } }
七、判断输赢ifwin
根据我们下五子棋的经验,能获胜的地方必定是最后落子的水平线、竖直线、和两个斜对角线,我们只需对其进行检索即可。ifwin的返回值决定之后的switch语句
弱弱的说一句,虽然看起来多,但很多都是重复的。
int Ifwin(char board[ROW][COL], int row, int col, int x, int y) { int ret; { ret = check_x(board, row, col, x, y); if (ret >= 5) return 0; ret = check_y(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_up(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_down(board, row, col, x, y); if (ret >= 5) return 0; } return 3; } int check_x(char board[ROW][COL], int row, int col, int x, int y)//检查x轴竖直方向 { int sum = 1; int old_x = x; while (x < row && board[x - 1][y - 1] == board[x][y - 1]) { sum++; x++; } x = old_x; while (x-2>= 0 && board[x - 1][y - 1] == board[x - 2][y - 1] ) { sum++; x--; } return sum; } int check_y(char board[ROW][COL], int row, int col, int x, int y)//检查y轴水平方向 { int sum = 1; int old_y = y; while (y<col && board[x-1][y-1] == board[x-1][y] ) { sum++; y++; } y = old_y; while (y-2 >= 0 && board[x-1][y-1] == board[x-1][y -2] ) { sum++; y--; } return sum; } int check_xy_up(char board[ROW][COL], int row, int col, int x, int y)//检查斜上45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y - 2 >= 0 && board[x - 1][y - 1] == board[x][y - 2]) { sum++; x++; y--; } x = old_x; y = old_y; while (x - 2 >= 0 && y <col && board[x - 1][y - 1] == board[x - 2][y]) { sum++; x--; y++; } return sum; } int check_xy_down(char board[ROW][COL], int row, int col, int x, int y)//检查斜下45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y <col && board[x - 1][y - 1] == board[x][y]) { sum++; x++; y++; } x = old_x; y = old_y; while (board[x-1][y-1] == board[x -2][y-2 ] && x-2>=0 && y-2 >=0) { sum++; x--; y--; } return sum; }
八、人机、人人模式的选择
初始选择界面
void game() { int input; char board[ROW][COL] = { 0 }; Initboard(board, ROW, COL); //初始化棋盘 Displayboard(board, ROW, COL); //展示棋盘 printf("请选择模式:1.人机;2.玩家对战\n"); printf("请选择:"); do{ scanf("%d", &input); printf("\n"); switch (input) { case 1:printf("游戏模式1开始!(注意:竖为x轴,横为y轴)\n"); game1(board, ROW, COL); break; case 2:printf("游戏模式2开始!(注意:竖为x轴,横为y轴)\n"); ; game2(board, ROW, COL); break; default:printf("请重新输入\n"); break; } } while (input != 1 && input != 2);//do while语句在输入错误时反复输入 }
game1的具体实现
void game1(char board[ROW][COL], int row, int col) { srand((unsigned int)time(NULL));//srand只要设置一次就可以,所以要放在while循环外 while (1) { int ret; int count = 0; int flag = 0; //判读玩家的下棋 int x; int y; printf("玩家落子,请依次输入x y坐标: "); scanf("%d%d", &x, &y); Playermove_1(board, row, col,&x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL)//全下满则认为平局 ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家获胜\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1)//用flag跳出while循环 break; //判断计算机的下棋 computermove(board, row, col); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("电脑获胜\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; } }
作者觉得写的是挺啰嗦,欢迎留言建议。game2和game1玩家一的内容很相近,就不赘述
九、作者遇到的坑点
1.输入的坐标和存在数组里的下标有减一的关系,在写的时候不要写忘记了
2.传址操作才能改变函数外的变量值
十、完整的代码
头文件就省了
int main() { int input; do{ system("cls");//清屏 menu(); scanf("%d", &input); switch (input) { case 1: printf("游戏开始\n\n"); game(); break; case 0: printf("退出游戏\n"); break; default: printf("请重新输入\n"); break; } Sleep(3000);//暂停3秒 } while (input);//do while语句实现可以反复玩 return 0; } void menu() { //完成菜单的初始化 printf("***********************\n"); printf("***********************\n"); printf("*****1.play 0.exit****\n"); printf("***********************\n"); printf("***********************\n"); printf("请输入:"); } 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 (j = 0; j < col; j++)//打印横向y坐标 { if (j == 0)//考虑到x轴所占的一格 { printf(" %d ", j + 1); } else { printf(" %d ", j + 1); } } printf("\n"); for (i = 0; i < row; i++)//打印数据 { for (j = 0; j < col; j++) { if (j == 0)//顺带打印竖向x坐标 { printf("%2d",i+1);//%md表示域宽为m printf(" %c ",board[i][j]); } else { printf(" %c ", board[i][j]); } //数字表示坐标 if (j < col - 1) printf("|"); } printf("\n"); //打印分割行 if (i < row - 1) { for (j = 0; j < col; j++) { if (j == 0)//同样考虑到y轴 printf(" ---"); else printf("---"); if (j < col - 1) printf("|"); } printf("\n");//别忘记这里也要换行 } } } void game() { int input; char board[ROW][COL] = { 0 }; Initboard(board, ROW, COL); //初始化棋盘 Displayboard(board, ROW, COL); //展示棋盘 printf("请选择模式:1.人机;2.玩家对战\n"); printf("请选择:"); do{ scanf("%d", &input); printf("\n"); switch (input) { case 1:printf("游戏模式1开始!(注意:竖为x轴,横为y轴)\n"); game1(board, ROW, COL); break; case 2:printf("游戏模式2开始!(注意:竖为x轴,横为y轴)\n"); ; game2(board, ROW, COL); break; default:printf("请重新输入\n"); break; } } while (input != 1 && input != 2);//do while语句在输入错误时反复输入 } void game1(char board[ROW][COL], int row, int col) { srand((unsigned int)time(NULL));//srand只要设置一次就可以,所以要放在while循环外 while (1) { int ret; int count = 0; int flag = 0; //判读玩家的下棋 int x; int y; printf("玩家落子,请依次输入x y坐标: "); scanf("%d%d", &x, &y); Playermove_1(board, row, col,&x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL)//全下满则认为平局 ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家获胜\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1)//用flag跳出while循环 break; //判断计算机的下棋 computermove(board, row, col); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("电脑获胜\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; } } void game2(char board[ROW][COL], int row, int col) { while (1) { int ret; int count = 0; int flag = 0; int x; int y; //判读玩家1的下棋 printf("玩家1落子,请输入坐标:(注意:竖为x轴,横为y轴)"); scanf("%d%d", &x, &y); Playermove_1(board, row, col, &x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家1获胜\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; //判断玩家2的下棋 printf("玩家2落子,请输入坐标:(注意:竖为x轴,横为y轴)"); scanf("%d%d", &x, &y); Playermove_2(board, row, col, &x, &y); count++; Displayboard(board, ROW, COL); if (count == ROW*COL) ret = 1; else ret = Ifwin(board, ROW, COL, x, y); switch (ret) { case 0:printf("玩家2获胜\n"); flag = 1; break; case 1:printf("平局\n"); flag = 1; break; default: break; } if (flag == 1) break; } } void Playermove_1(char board[ROW][COL], int row, int col, int *px, int*py)//ROW可以省,COL不行 { int x = *px; int y = *py; while (1) { if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入坐标的合法性 { if (board[x -1][y- 1] == ' ')//保证落子点为空 { board[x-1 ][y -1] = '*'; *px = x; *py = y;//如果开始xy输入不合法,要对外部xy修改,所以要传址操作 break; } else { printf("你不能在此处落子\n"); printf("玩家1落子,请重新输入x y坐标: "); scanf("%d%d", &x, &y); } } else { printf("输入坐标不合法\n"); printf("玩家落子,请重新输入x y坐标: "); scanf("%d%d", &x, &y); } } } void Playermove_2(char board[ROW][COL], int row, int col, int *px, int*py) { int x = *px; int y = *py; while (1) { if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入坐标的合法性 { if (board[x - 1][y - 1] == ' ')//保证落子点为空 { board[x - 1][y - 1] = '#'; *px = x; *py = y; break; } else { printf("你不能在此处落子\n"); printf("玩家2落子,请重新输入x y坐标: "); scanf("%d%d", &x, &y); } } else { printf("输入坐标不合法\n"); printf("玩家落子,请重新输入x y坐标: "); scanf("%d%d", &x, &y); } } } void computermove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) { x = rand() % ROW; y = rand() % COL; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } int Ifwin(char board[ROW][COL], int row, int col, int x, int y) { int ret; { ret = check_x(board, row, col, x, y); if (ret >= 5) return 0; ret = check_y(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_up(board, row, col, x, y); if (ret >= 5) return 0; ret = check_xy_down(board, row, col, x, y); if (ret >= 5) return 0; } return 3; } int check_x(char board[ROW][COL], int row, int col, int x, int y)//检查x轴竖直方向 { int sum = 1; int old_x = x; while (x < row && board[x - 1][y - 1] == board[x][y - 1]) { sum++; x++; } x = old_x; while (x-2>= 0 && board[x - 1][y - 1] == board[x - 2][y - 1] ) { sum++; x--; } return sum; } int check_y(char board[ROW][COL], int row, int col, int x, int y)//检查y轴水平方向 { int sum = 1; int old_y = y; while (y<col && board[x-1][y-1] == board[x-1][y] ) { sum++; y++; } y = old_y; while (y-2 >= 0 && board[x-1][y-1] == board[x-1][y -2] ) { sum++; y--; } return sum; } int check_xy_up(char board[ROW][COL], int row, int col, int x, int y)//检查斜上45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y - 2 >= 0 && board[x - 1][y - 1] == board[x][y - 2]) { sum++; x++; y--; } x = old_x; y = old_y; while (x - 2 >= 0 && y <col && board[x - 1][y - 1] == board[x - 2][y]) { sum++; x--; y++; } return sum; } int check_xy_down(char board[ROW][COL], int row, int col, int x, int y)//检查斜下45度 { int sum = 1; int old_x = x; int old_y = y; while (x<row && y <col && board[x - 1][y - 1] == board[x][y]) { sum++; x++; y++; } x = old_x; y = old_y; while (board[x-1][y-1] == board[x -2][y-2 ] && x-2>=0 && y-2 >=0) { sum++; x--; y--; } return sum; }
如果对你有帮助和启发,作者感到很高兴。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。