c语言 实现三子棋(电脑是随机下棋子的)


前言

三子棋简单来说就是井字棋
规则:双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。
大致过程:
在一个棋盘上,一个人率先下棋子,然后就是另外一个人下棋,直到一方的棋子能够连成一条直线或是棋盘下满了但双方都没有赢(和棋)


经过了解,我们第一步需要设计一个简单的棋盘
例如:
在这里插入图片描述

一、设计一个棋盘

1、'手动’打印棋盘

我们可以把一行看做一个整体,再将每一行打印出来
每一行就是:
在这里插入图片描述

void print_board()
{
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		printf("   |   |   \n");
		printf("---|---|---\n");
	}
}

int main()
{
	//将打印棋盘封装为一个函数
	print_board();
	return 0;
}

运行结果:
在这里插入图片描述
很显然:框起来的是多余的,咱们不需要它。
在这里插入图片描述
改进棋盘:

void print_board()
{
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		printf("   |   |   \n");
		//当到第三行是不想"---|---|---"的
		if(i<3-1)
			printf("---|---|---\n");
	}
}

int main()
{

	print_board();
	return 0;
}

运行结果:
在这里插入图片描述
看来我们已经成功打印出棋盘了,如果我们想打印出更大的棋盘呢?,那每次修改棋盘的大小都需要我们自己动手修改程序,是不是太麻烦呢!!

2、'自动’打印棋盘

举个例子:还是打印三子棋的棋盘
我们定义一个变量(ROW)控制行,定义一个变量(COL)控制列,当然这个变量是可以修改的(C语言中我们可以使用宏定义)。
我们还是可以把一行看做一个整体,再将每一行打印出来
每一行就是:
在这里插入图片描述
再把每一行分为:
第一行:空格、空格、空格和 | 。
第二行:-、-、- 和 | 。

用COL控制它们的数量

代码实现:


#define ROW 3
#define COL 3

void print_board(int row,int col)
{
	int j = 0;
	//
	for (j = 0;j < col;j++)
	{
		printf("   ");//这里是打印三个空格,后面的时候中间的空格是用来下棋子的
		if (j < col - 1)
			printf("|");
	}
	printf("\n");
	for (j = 0;j < col;j++)
	{
		printf("---");
		if (j < col - 1)
			printf("|");
	}
}

int main()
{
	print_board(ROW,COL);
	return 0;
}

运行结果:
在这里插入图片描述
打印三个这样的东西:

#define ROW 3
#define COL 3

void print_board(int row,int col)
{
	int i = 0;
	int j = 0;
	for (i = 0;i < row; i++)
	{
		//打印 空格空格空格|
		for (j = 0;j < col;j++)
		{
			printf("   ");
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印---|
		for (j = 0;j < col;j++)
		{
			printf("---");
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
	}
}



int main()
{
	print_board(ROW,COL);
	return 0;
}

运行结果:
在这里插入图片描述
框起来的还是不需要的,将它去除。

#define ROW 3
#define COL 3

void print_board(int row,int col)
{
	int i = 0;
	int j = 0;
	for (i = 0;i < row; i++)
	{
		for (j = 0;j < col;j++)
		{	
			printf("   ");//打印三个空格,中间的空格是落棋子的
			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");
	}
}



int main()
{
	print_board(ROW,COL);
	return 0;

}

运行结果:
在这里插入图片描述
这样我们想修改棋盘的大小时,只需要修改宏定义的ROW和COL了,是不是很方便了。
例如:打印5*5的棋盘
在这里插入图片描述
这样一来,棋盘就已经设计好了,接下来就是下棋了。

二、下棋

1、初始化棋盘

我们可以定义一个二维数组,将这个二维数组的全部元素初始化为空格(因为空格是透明的)。还是将它封装为一个函数(init_board)
这个二维数组其实就是记录棋盘内容的。
在这里插入图片描述

void init_board(char board[][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] = ' ';
		}

	}

}

如果我们要使用print_board打印棋盘的元素的话,还要需要修改一下print_board。
前面提到三个空格中间的一个就是落棋子的(即放棋盘元素的位置)

void print_board(char board[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0;i < row; i++)
	{
		for (j = 0;j < col;j++)
		{	
			//%c是打印字符,打印的是棋盘元素的第i行第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");
	}
}

这样我们就可以打印数组内容了,举个例子:我将数组全部初始化为‘*’
print_board结果就是:

在这里插入图片描述

2、玩家下棋

玩家输入对应的棋盘坐标,我们就把数组对应的坐标赋值为’*',这就相当玩家落棋了。封装为函数(play_move)

代码实现:

void player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请选择下棋的位置:>");
		scanf("%d %d", &x, &y);
		//输入棋盘的有效下标才有用
		if (x >= 1 && x <= row && y >= 1 && y <= col && board[x-1][y-1]==' ')
		{
				board[x-1][y-1] = '*';
				break;
		}
		else
		{
			printf("输入错误!\n");
		}
	}
}

3、电脑下棋

电脑生成两个随机数(0<=随机数的值<=2),我们再将数组下标对应的这个两个随机数赋值为’#'。这样电脑下棋就好了
当然,这个两个随机数不能重复。数组已经赋值了的下标也不能使用。

代码实现:




void computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	while (1)
	{
		//rang是一个库函数,它是用来生成随机数的,随机数%row(3),就是生成0到2的随机数。rand是用使用条件的,后面再说。
		int x = rand() % row;
		int y = rand() % col;
		
		//is_full()这个函数是判断数组元素是否已经满了,满了的话就只能终止循环。后面会实现
		if (is_full(board, row, col))
			break;
		if (x >= 0 && x < row && y >= 0 && y < col && board[x][y] == ' ')
		{
				board[x][y] = '#';
				break;
		}

	}
	
}

4、判断棋盘的情况

玩家和电脑下完棋后,有三种情况
详细一点就是:
第一种:电脑或玩家完成如图的任意一种情况,连起来的数组元素是相同的。
在这里插入图片描述
第二种:数组已经装满了,但还没有人赢(和棋)

第三种:数组还没有装满,也没有人赢,这种情况就还需要继续下棋。

还是写成一个函数,既然这个函数需要反应多种情况,我们就把它的返回类型设置为char,第一种情况就返回已经连成一条线的任意一个元素,第二种就返回’Q’(表示平局),第三种就返回’C’(表示继续游戏)。

代码实现:

//判断数组元素是否已经全部初始化(棋盘是否满了)
int is_full(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++)
		{
			//如果棋盘有元素为空格,就还没满,
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	//如果for没有return 0,就是说明数组全部的元素都已经初始化(即棋盘落棋落满了)
	return 1;
}




char is_win(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][1];
		//这是竖三列
		else if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
			return board[0][i];
		//这是对角线的两种情况
		else if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
			return board[1][1];
		else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
			return board[1][1];

	}
	//判断棋盘是否满了,满了的话就返回1,if语句就会return Q,跳出当前函数
	if (is_full(board, row, col))
		return 'Q';
	else
		return 'C';

}

三、组装

前面大致介绍了如何做一个棋盘,玩家如何下棋,电脑如何下棋,以及判断棋盘的情况。
那我们如何将它组成一个可以执行的小游戏呢?
我们需要一个test.c(测试游戏逻辑)
还要game.c (实现三子棋的函数)和game.h(函数声明)
直接看代码:
首先是:game.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


#define ROW 3
#define COL 3

void game();
void test();
//初始化棋盘
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋
void player_move(char board[ROW][COL], int row, int col);
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col);
//判断输赢
char is_win(char board[ROW][COL], int row, int col);
//玩家赢返回'*'
//电脑赢返回'#'
//平局返回'Q'
//剩余的一种情况就是继续下棋,返回'C'

接下来是:game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"



//初始化棋盘
void init_board(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 print_board(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++)
		{
			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 < row - 1)
					printf("|");
			}
			printf("\n");

		}
	}
	
}

//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
	printf("玩家下棋\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请选择下棋的位置:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col && board[x-1][y-1]==' ')
		{
				board[x-1][y-1] = '*';
				break;
		}
		else
		{
			printf("输入错误!\n");
		}
	}
}

int is_full(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++)
		{
			//如果棋盘有元素为空格,就还没满,
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}


//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (is_full(board, row, col))
			break;
		if (x >= 0 && x < row && y >= 0 && y < col && board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
			
			
		}

	}
	
}


//判断输赢
char is_win(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][1];
		else if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
			return board[0][i];
		else if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
			return board[1][1];
		else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
			return board[1][1];

	}
	if (is_full(board, row, col))
		return 'Q';
	else
		return 'C';

}

最后是:test.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 ret = ' ';
	srand(time(NULL));
	char board[ROW][COL] = { 0 };
	init_board(board,ROW,COL);
	print_board(board, ROW, COL);
	while (1)
	{
		player_move(board, ROW, COL);
		print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}


		computer_move(board, ROW, COL);
		print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	
	}
	if (ret == '*')
		printf("玩家赢\n");
	else if (ret == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");



}


void test()
{
	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);


}



int main()
{
	test();
	return 0;
}

最后来看看游戏的运行过程吧。

QQ录屏20221108172525


总结

以上就是三子棋的全部代码了,快去试一试吧。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,设计三子棋游戏可以分为以下几个步骤: 1. 定义棋盘:通常使用一个三行三列的二维数组来表示棋盘,用数字0表示空位,用数字1表示玩家1下的棋子,用数字2表示玩家2下的棋子。 2. 实现落子功能:用户输入行列坐标,程序判断该位置是否为空位,如果是则将该位置设置为当前玩家下的棋子。 3. 判断胜负:每次玩家下完棋后,程序需要判断是否有一方取得胜利,可以通过遍历棋盘来实现。 4. 实现人机对战:可以使用随机数来模拟电脑的落子,也可以使用一些简单的算法来提高电脑的智能程度。 下面是一个简单的C语言三子棋游戏代码示例,供参考: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> int chessboard[3][3]; // 棋盘 int check_win(int player) // 判断胜负 { int i, j; for (i = 0; i < 3; i++) { if (chessboard[i][0] == player && chessboard[i][1] == player && chessboard[i][2] == player) { return 1; } if (chessboard[0][i] == player && chessboard[1][i] == player && chessboard[2][i] == player) { return 1; } } if (chessboard[0][0] == player && chessboard[1][1] == player && chessboard[2][2] == player) { return 1; } if (chessboard[0][2] == player && chessboard[1][1] == player && chessboard[2][0] == player) { return 1; } return 0; } void print_chessboard() // 打印棋盘 { int i, j; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { if (chessboard[i][j] == 0) { printf(" "); } else if (chessboard[i][j] == 1) { printf("X"); } else if (chessboard[i][j] == 2) { printf("O"); } if (j < 2) { printf("|"); } } printf("\n"); if (i < 2) { printf("-+-+-\n"); } } } int main() { int player = 1; // 玩家先手 int row, col; srand((unsigned)time(NULL)); // 初始化随机数生成器 printf("Welcome to the Tic-Tac-Toe game!\n"); printf("Player 1: X\n"); printf("Player 2: O\n"); while (1) { printf("Player %d's turn.\n", player); if (player == 1) { printf("Please input the row and column numbers to place your chess(X).\n"); scanf("%d%d", &row, &col); if (chessboard[row][col] != 0) { printf("This place has been taken, please choose another place.\n"); continue; } chessboard[row][col] = 1; } else { printf("Thinking...\n"); while (1) { row = rand() % 3; col = rand() % 3; if (chessboard[row][col] == 0) { break; } } chessboard[row][col] = 2; } print_chessboard(); if (check_win(player)) { printf("Player %d wins!\n", player); break; } if (player == 1) { player = 2; } else { player = 1; } } return 0; } ``` 注意:以上代码仅作为参考,可能存在一些漏洞和不足之处,需要在实际使用中进行完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值