当前位置:网站首页>C语言实现三子棋?五子棋?不,是n子棋
C语言实现三子棋?五子棋?不,是n子棋
2022-07-24 05:16:00 【泡泡牛奶】
目录
前言
实现这样一个代码程序,其实并不算太难,所需要的知识量概括为,数组,函数,循环语句,分支语句。在这之中想必最为复杂的就是判断是否获胜了吧。

废话不多说,让我们开始吧。
1、 game_tic.h
game_tic.h : 自定义头文件,主要用于:
1 . 库函数的包含2 . 自定义函数的申明
3 . 定义棋盘大小
#ifndef GAME_TIC_H
#define GAME_TIC_H
//棋盘大小
#define ROW 15
#define COL 15
//方便计算用
#define ROWS (ROW + 1)
#define COLS (COL + 1)
//防止用数组检索的时候,出现非法访问
#define ROWSS (ROWS + 1)
#define COLSS (COLS + 1)
#define NUM 5// 确定n子棋
//包含的头文件
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <stdlib.h>
//函数声明
void game_tic();
void InitBoard(char board[ROWSS][COLSS]);
void PrintBoard(char board[ROWSS][COLSS]);
void PlayerMove(char board[ROWSS][COLSS], int PlayerMark[2], char p1);
void ComputerMove(char board[ROWSS][COLSS], int computmark[2], char p2);
char IsWin(char board[ROWSS][COLSS], int x, int y, char el);
#endif2、 test.c
test.c : 用于实现大致界面
#include "game_tic.h"
void menu()
{
int input = 0;
do
{
printf("********************************\n");
printf("****** 0.返回 *******\n");
printf("****** 1. n子棋游戏 *******\n");
printf("****** 2.(还没想好) *******\n");
printf("********************************\n");
printf("请选择 >: ");
scanf("%d", &input);
switch (input)
{
case 1:
game_tic();
break;
default:
system("cls");
printf("输入错误,请从新输入\n");
break;
}
} while (input);
}
void start()//选择开始菜单
{
int input = 0;
do
{
printf("************************\n");
printf("****** 1.开始游戏 ****\n");
printf("****** 0.退出程序 ****\n");
printf("************************\n");
printf("请输入 >: ");
scanf("%d", &input);
if (input == 1)
{
menu();
}
else if (input != 0)
{
printf("输入错误,请从新输入\n");
system("cls");//清屏
}
} while (input);
}
int main()
{
start();
return 0;
}
3 、 game_tic.c
game_tic.c : 用于实现游戏内容
3.1 游戏主体
因为数组在进行传参的时候传的是首元素地址,数组在使用其它函数的时候不会想形参一样进行销毁,所以我们可以引用一个数组来保存坐标。
注意:
ComputMark[2] = { 0 }; 用于记录电脑坐标
PlayerMark[2] = { 0 }; 用于记录玩家坐标
此做法在本程序内起到关键作用
//游戏主体
void game_tic()
{
srand((unsigned int)time(NULL));
int x = 0;
int y = 0;
char board[ROWSS][COLSS] = { 0 };
int ComputMark[2] = { 0 };//记录电脑的坐标
int PlayerMark[2] = { 0 };//记录玩家的坐标
InitBoard(board);
PrintBoard(board);
while (1)
{
PlayerMove(board, PlayerMark, '*');
PrintBoard(board);
x = PlayerMark[0];
y = PlayerMark[1];
if ('*' == IsWin(board, x, y, '*'))
{
printf("玩家获胜\n");
break;
}
if (IsFull(board))
{
printf("平局\n");
break;
}
ComputerMove(board, ComputMark,'#');
PrintBoard(board);
x = ComputMark[0];
y = ComputMark[1];
if ('#' == IsWin(board, x, y, '#'))
{
printf("电脑获胜\n");
break;
}
if (IsFull(board))
{
printf("平局\n");
break;
}
}
}3.2 游戏的具体实现
3.2.1 打印棋盘
void PrintBoard(char board[ROWSS][COLSS])
{
int i = 0;
int j = 0;
system("cls");
for (i = 1; i < ROWS; i++)//打印横坐标
{
printf("%4d", i);
}
printf("\n");
for (i = 1; i < ROWS; i++)
{
printf("%-2d", i);//打印列坐标
for (j = 1; j < COLS; j++)
{
printf(" %c ", board[i][j]);
if(j != COLS - 1)
printf("|");
}
printf("\n ");
for (j = 1; j < COLS && i < ROWS - 1; j++)
{
printf("----");
}
printf("\n");
}
}效果图展示:
ROW 为 3,COL 为 3 的时候 (三子棋棋盘)

ROW 为 15,COL 为 15 的时候 (五子棋棋盘)

3.2.2 初始化棋盘
在每次进行游戏之前需要对棋盘进行初始化,即里面元素全放 空格 。
void InitBoard(char board[ROWSS][COLSS])
{
int i = 0;
int j = 0;
for (i = 0; i < ROWSS; i++)
{
for (j = 0; j < COLSS; j++)
{
board[i][j] = ' ';
}
}
}3.2.3 玩家进行下棋
在接收到一个可用坐标时,将其记录在数组内
注意:
如果想实现 玩家 VS 玩家 ,可以将 电脑下棋 改为 玩家下棋
void PlayerMove(char board[ROWSS][COLSS],int PlayerMark[2], char p1)
{
int x = 0;
int y = 0;
while (1)
{
printf("请输入坐标 (x,y)");
scanf("%d,%d", &x, &y);
if (x > 0 && x < COLSS && y > 0 && y < ROWSS)
{
if (board[y][x] == ' ')
{
board[y][x] = p1;
break;
}
else
{
printf("输入的坐标已被占用,请从新输入\n");
}
}
else
{
printf("非法输入坐标,请从新输入\n");
}
}
PlayerMark[0] = x;
PlayerMark[1] = y;
}3.2.4 电脑下棋
电脑下棋的时候,我使用了 rand( ) 函数进行随机取值
如果想了解函数的用法请参考 :http://cplusplus.com/reference/cstdlib/rand/?kw=rand
void ComputerMove(char board[ROWSS][COLSS], int computmark[2], char p2)
{
while (1)
{
int x = rand() % COL + 1;
int y = rand() % ROW + 1;
computmark[0] = x;
computmark[1] = y;
if (board[y][x] == ' ')
{
board[y][x] = p2;
break;
}
}
}3.2.5 判断是否获胜
IsCount : 返回当前下棋坐标周围的棋子数量
char IsWin(char board[ROWSS][COLSS],int x, int y, char el)
{
//继续 返回 'C'
//获胜 返回 e1
if (NUM == IsCount(board, x, y))
{
return el;
}
else
{
return 'C';
}
}思路:
落下一个棋子,记录它的坐标,然后向4个方向去寻找相同的棋子并记录数量,用一个数组去存储每个方向的棋子数量,取最大值返回
毕竟也不能保证不会出现这样的情况
//计数
int IsCount(char board[ROWSS][COLSS], int x, int y)
{
int i = 0;
int moveX = x;
int moveY = y;
int count = 1;//计数
int countmax = 0;//4个方向上的最多棋子数量
int countarr[4] = { 0 };//记录 4 个方向上的棋子数量
// [0] 为左上斜
// [1] 为右上斜
// [2] 为竖
// [3] 为横
//左上斜
if (board[moveY + 1][moveX - 1] == board[moveY][moveX] ||
board[moveY - 1][moveX + 1] == board[moveY][moveX])
{
count = 1;
//左上角
for (i = 0, moveX = x, moveY = y;
board[moveY + 1][moveX - 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX += 1;
moveY -= 1;
}
//右下角
for (i = 0, moveX = x, moveY = y;
board[moveY - 1][moveX + 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX += 1;
moveY -= 1;
}
countarr[0] = count;
moveX = x;
moveY = y;
}
//右上斜
if (board[moveY - 1][moveX - 1] == board[moveY][moveX] ||
board[moveY + 1][moveX + 1] == board[moveY][moveX])
{
count = 1;
for (i = 0, moveX = x, moveY = y;
board[moveY - 1][moveX - 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX -= 1;
moveY -= 1;
}
for (i = 0, moveX = x, moveY = y;
board[moveY + 1][moveX + 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX += 1;
moveY += 1;
}
countarr[1] = count;
moveX = x;
moveY = y;
}
//竖
if (board[moveY][moveX] == board[moveY + 1][moveX] ||
board[moveY][moveX] == board[moveY - 1][moveX])
{
count = 1;
//向上计数
for (i = 0, moveX = x, moveY = y; (moveY + 1 <= ROW) && i < NUM &&
(board[moveY][moveX] == board[moveY + 1][moveX])
; i++)
{
count++;
moveY += 1;
}
for (i = 0, moveX = x, moveY = y; (moveY - 1 >= 0) && i < NUM &&
(board[moveY][moveX] == board[moveY - 1][moveX])
; i++)
{
count++;
moveY -= 1;
}
countarr[2] = count;
moveX = x;
moveY = y;
}
//横
if (board[moveY][moveX] == board[moveY][moveX + 1] ||
board[moveY][moveX] == board[moveY][moveX - 1])
{
count = 1;
for (i = 0, moveX = x,moveY = y; (moveX + 1 <= COL) && i < NUM &&
(board[moveY][moveX] == board[moveY][moveX + 1])
; i++)
{
count++;
moveX += 1;
}
for (i = 0, moveX = x, moveY = y; (moveX - 1 >= 0) && i < NUM &&
(board[moveY][moveX] == board[moveY][moveX - 1])
; i++)
{
count++;
moveX -= 1;
}
countarr[3] = count;
}
countmax = arrmax(countarr);
return countmax;
}//判断4个方向里的棋子数量的最大值
int arrmax(int arr[4])
{
int i = 0;
int max = arr[0];
for (i = 1; i < 4; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
3.2.6 判断棋盘是否已经满
若棋盘已满,还没有分出胜负,则退出游戏,按平局处理
int IsFull(char board[ROWSS][COLSS])
{
int i = 0;
int j = 0;
for (i = 1; i < ROWS; i++)
{
for (j = 1; j < COLS; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}4、代码展示
4.1 game_tic.h
#ifndef GAME_TIC_H
#define GAME_TIC_H
//棋盘大小
#define ROW 15
#define COL 15
#define ROWS (ROW + 1)
#define COLS (COL + 1)
#define ROWSS (ROWS + 1)
#define COLSS (COLS + 1)
#define NUM 5// 确定n子棋
//包含的头文件
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <stdlib.h>
//函数声明
void game_tic();
void InitBoard(char board[ROWSS][COLSS]);
void PrintBoard(char board[ROWSS][COLSS]);
void PlayerMove(char board[ROWSS][COLSS], int PlayerMark[2], char p1);
void ComputerMove(char board[ROWSS][COLSS], int computmark[2], char p2);
char IsWin(char board[ROWSS][COLSS], int x, int y, char el);
#endif4.2 test.c
#include "game_tic.h"
void menu()
{
int input = 0;
do
{
printf("********************************\n");
printf("****** 0.返回 *******\n");
printf("****** 1. n子棋游戏 *******\n");
printf("****** 2.(还没想好) *******\n");
printf("********************************\n");
printf("请选择 >: ");
scanf("%d", &input);
switch (input)
{
case 1:
game_tic();
break;
default:
system("cls");
printf("输入错误,请从新输入\n");
break;
}
} while (input);
}
void start()//选择开始菜单
{
int input = 0;
do
{
printf("************************\n");
printf("****** 1.开始游戏 ****\n");
printf("****** 0.退出程序 ****\n");
printf("************************\n");
printf("请输入 >: ");
scanf("%d", &input);
if (input == 1)
{
menu();
}
else if (input != 0)
{
printf("输入错误,请从新输入\n");
system("cls");//清屏
}
} while (input);
}
int main()
{
start();
return 0;
}4.3 game_tic.c
#include "game_tic.h"
//判断棋盘是否满
int IsFull(char board[ROWSS][COLSS])
{
int i = 0;
int j = 0;
for (i = 1; i < ROWS; i++)
{
for (j = 1; j < COLS; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
int arrmax(int arr[4])
{
int i = 0;
int max = arr[0];
for (i = 1; i < 4; i++)
{
if (arr[i] > max)
{
max = arr[i];
}
}
return max;
}
//计数
int IsCount(char board[ROWSS][COLSS], int x, int y)
{
int i = 0;
int moveX = x;
int moveY = y;
int count = 1;//计数
int countmax = 0;//4个方向上的最多棋子数量
int countarr[4] = { 0 };//记录 4 个方向上的棋子数量
// [0] 为左上斜
// [1] 为右上斜
// [2] 为竖
// [3] 为横
//左上斜
if (board[moveY + 1][moveX - 1] == board[moveY][moveX] ||
board[moveY - 1][moveX + 1] == board[moveY][moveX])
{
count = 1;
//左上角
for (i = 0, moveX = x, moveY = y;
board[moveY + 1][moveX - 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX += 1;
moveY -= 1;
}
//右下角
for (i = 0, moveX = x, moveY = y;
board[moveY - 1][moveX + 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX += 1;
moveY -= 1;
}
countarr[0] = count;
moveX = x;
moveY = y;
}
//右上斜
if (board[moveY - 1][moveX - 1] == board[moveY][moveX] ||
board[moveY + 1][moveX + 1] == board[moveY][moveX])
{
count = 1;
for (i = 0, moveX = x, moveY = y;
board[moveY - 1][moveX - 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX -= 1;
moveY -= 1;
}
for (i = 0, moveX = x, moveY = y;
board[moveY + 1][moveX + 1] == board[moveY][moveX] && i < NUM
; i++)
{
count++;
moveX += 1;
moveY += 1;
}
countarr[1] = count;
moveX = x;
moveY = y;
}
//竖
if (board[moveY][moveX] == board[moveY + 1][moveX] ||
board[moveY][moveX] == board[moveY - 1][moveX])
{
count = 1;
//向上计数
for (i = 0, moveX = x, moveY = y; (moveY + 1 <= ROW) && i < NUM &&
(board[moveY][moveX] == board[moveY + 1][moveX])
; i++)
{
count++;
moveY += 1;
}
for (i = 0, moveX = x, moveY = y; (moveY - 1 >= 0) && i < NUM &&
(board[moveY][moveX] == board[moveY - 1][moveX])
; i++)
{
count++;
moveY -= 1;
}
countarr[2] = count;
moveX = x;
moveY = y;
}
//横
if (board[moveY][moveX] == board[moveY][moveX + 1] ||
board[moveY][moveX] == board[moveY][moveX - 1])
{
count = 1;
for (i = 0, moveX = x,moveY = y; (moveX + 1 <= COL) && i < NUM &&
(board[moveY][moveX] == board[moveY][moveX + 1])
; i++)
{
count++;
moveX += 1;
}
for (i = 0, moveX = x, moveY = y; (moveX - 1 >= 0) && i < NUM &&
(board[moveY][moveX] == board[moveY][moveX - 1])
; i++)
{
count++;
moveX -= 1;
}
countarr[3] = count;
}
countmax = arrmax(countarr);
return countmax;
}
char IsWin(char board[ROWSS][COLSS],int x, int y, char el)
{
//继续 返回 'C'
//获胜 返回 e1
if (NUM == IsCount(board, x, y))
{
return el;
}
else
{
return 'C';
}
}
//电脑 游玩
void ComputerMove(char board[ROWSS][COLSS], int computmark[2], char p2)
{
while (1)
{
int x = rand() % COL + 1;
int y = rand() % ROW + 1;
computmark[0] = x;
computmark[1] = y;
if (board[y][x] == ' ')
{
board[y][x] = p2;
break;
}
}
}
// 玩家 游玩
void PlayerMove(char board[ROWSS][COLSS],int PlayerMark[2], char p1)
{
int x = 0;
int y = 0;
while (1)
{
printf("请输入坐标 (x,y)");
scanf("%d,%d", &x, &y);
if (x > 0 && x < COLSS && y > 0 && y < ROWSS)
{
if (board[y][x] == ' ')
{
board[y][x] = p1;
break;
}
else
{
printf("输入的坐标已被占用,请从新输入\n");
}
}
else
{
printf("非法输入坐标,请从新输入\n");
}
}
PlayerMark[0] = x;
PlayerMark[1] = y;
}
//初始化棋盘
void InitBoard(char board[ROWSS][COLSS])
{
int i = 0;
int j = 0;
for (i = 0; i < ROWSS; i++)
{
for (j = 0; j < COLSS; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void PrintBoard(char board[ROWSS][COLSS])
{
int i = 0;
int j = 0;
system("cls");
for (i = 1; i < ROWS; i++)//打印横坐标
{
printf("%4d", i);
}
printf("\n");
for (i = 1; i < ROWS; i++)
{
printf("%-2d", i);//打印列坐标
for (j = 1; j < COLS; j++)
{
printf(" %c ", board[i][j]);
if(j != COLS - 1)
printf("|");
}
printf("\n ");
for (j = 1; j < COLS && i < ROWS - 1; j++)
{
printf("----");
}
printf("\n");
}
}
//游戏主体
void game_tic()
{
srand((unsigned int)time(NULL));
int x = 0;
int y = 0;
char board[ROWSS][COLSS] = { 0 };
int ComputMark[2] = { 0 };
int PlayerMark[2] = { 0 };
InitBoard(board);
PrintBoard(board);
while (1)
{
PlayerMove(board, PlayerMark, '*');
PrintBoard(board);
x = PlayerMark[0];
y = PlayerMark[1];
if ('*' == IsWin(board, x, y, '*'))
{
printf("玩家获胜\n");
break;
}
if (IsFull(board))
{
printf("平局\n");
break;
}
ComputerMove(board, ComputMark,'#');
PrintBoard(board);
x = ComputMark[0];
y = ComputMark[1];
if ('#' == IsWin(board, x, y, '#'))
{
printf("电脑获胜\n");
break;
}
if (IsFull(board))
{
printf("平局\n");
break;
}
}
}5、一定要看这里
既然你都看到这里了
如果对你右帮助或者觉得好的话,请给一个赞φ(゜▽゜*)*
如果喜欢作者或者想看更多内容的话,请点一下关注(´▽`ʃ*ƪ)
如果你怕找不到这篇博客,有一个放走丢的办法,看到那个星星了吗,点一下有惊喜哦

咱也不是是说特别想要 ,就是想请您可怜可怜这位卑微的博主吧
边栏推荐
猜你喜欢

Beginners' preparation for the Blue Bridge Cup (University Programming learning history records, topic ideas for students who need to prepare for the Blue Bridge Cup)

Hotel IPTV digital TV system solution

Jsp+dao integration

Performance test process
![Embedded system transplantation [2] - Construction of cross development environment](/img/96/8d209c04e41675fc0efaa872c35615.png)
Embedded system transplantation [2] - Construction of cross development environment

C语言入门篇 概述

1. Pedestrian recognition based on incremental occlusion generation and confrontation suppression

AiN 0722 签到

web开发
![[deep learning] (III) image classification](/img/8a/86b8ec6951f112f47be816378ab7d8.png)
[deep learning] (III) image classification
随机推荐
力扣、牛客网->链表相关题目(篇一)(c语言)
View progress!!! RPM installation!!!
csgo部分常用服务器指令与一些绑定指令整理
c2-随机产生函数种子seed、numpy.random.seed()、tf.random.set_seed学习+转载整理
Generics and annotations
DNS domain name resolution service
Chapter5 foundation of deep learning
OSS文件上传
Create and delete databases using databases
C语言入门篇 二.函数
finally和return的执行顺序
Machine vision learning summary
NumPy 统计相关函数示例教程
Basic knowledge of MySQL database
反射
纯小白教程 在idea里使用Druid数据库连接池
JMeter upload and download files
用双向链表实现栈(C)
Theoretical basis of machine learning
Embedded system transplantation [3] - uboot burning and use
