C language---Tic Tac Toe (Three Pieces)


1 Game introduction and random numbers

1.1 Game introduction

Tic-Tac-Toe, also known as Tic-Tac-Toe in English, is a connecting game played on a 3*3 grid. It is named because the board generally has no borders and the grid lines are arranged in a tic-tac-toe pattern. The only tools required for the game are paper and pen. Then the two players, representing O and X respectively, take turns leaving marks on the grid (generally the player who goes first is .
Click here to enter the Tic Tac Toe link

I tied with the computer
Playing chess with myself, I won

1.2 Generation of random numbers

  • 1 rand() function
  • int rand(void)

Generate random numbers
Return pseudo-random integers between 0 and RAND_MAX. (RAND_MAX is 32767, the maximum binary original code is 0111111111111111=215-1=32767)
This number is generated by an algorithm that returns an apparently unrelated sequence of numbers every time it is called. The algorithm uses a seed to generate a sequence that should be initialized to some unique value using the function srand.
RAND_MAX is a constant defined in .
The typical way to use rand to generate trivial pseudo-random numbers within a determined range is to multiply the return value modulo the span of the range and add the initial value of the range:

v1 = rand() % 100;         // v1 范围 0 to 99
v2 = rand() % 100 + 1;     // v2 范围 1 to 100
v3 = rand() % 30 + 1985;   // v3 范围 1985-2014

Note that this modulo operation does not generate uniformly distributed random numbers across the span.

  • 2 The sand function is used to initialize the random number generator
  • void srand(unsigned int seed);
  • Call srand before calling rand, modify the seed parameter to generate a random number seed
int main()
{
    
    
	void srand(unsigned int seed);
	return 0;
}
  • 3 time()
    The time function can obtain the time and needs to reference the header file time.h
time_t time(time_t* timer);
  • Generate true random numbers
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
    
    
	srand((unsigned int)time(NULL));
	//srand 的参数是unsigned int 类型,强制转换,
	//time(NULL)返回一段时间戳
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());
	printf("%d\n", rand());

	return 0;
}

Insert image description here

1.3 Board size and symbols

Define Tic-Tac-Toe.hthe size of the chessboard rows, the symbols of the players and the computer in to facilitate subsequent modifications.

#define ROW 3
#define COL 3

#define Player_Choice 'X'
#define Computer_Choice 'O'
//#define Player_Choice '√'
//#define Computer_Choice '×'

2 Design Games

2.1 Initialize the chessboard

Define all elements of the two-dimensional array as "empty" and wait for the subsequent addition of Player_ChoicesumComputer_Choice

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] = ' ';
		}
	}
}

2.2 Print the chessboard

We move towards this %c | %c | %c \nand ---|---|---\nprint, designing the checkerboard shape.
Subsequent changes to the board size can be made via Change ROWand COLQuick Change.
We %c |think that one group does not exist in the last group |, ---|and the same reason applies. Need to judge individually

//2 打印棋盘
void DispalyBoard(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++)
		{
    
    
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印分割信息
		if (i < row - 1)
		{
    
    
			int j = 0;
			for (j = 0; j < col; j++)
			{
    
    
				printf("---");
				if (j < col - 1)
					printf("|");
			}
			printf("\n");
		}
	}
}

Insert image description here
Insert image description here

2.3 Players play chess

There are three points to pay attention to:
1. The input coordinate format
2. Whether the input coordinates are occupied
3. Whether the input coordinate range is correct

void PlayerMove(char board[ROW][COL], int row, int col)
{
    
    
	int x = 0;
	int y = 0;
	printf("玩家下棋:\n");

	while (1)
	{
    
    
		printf("请输入坐标:>");
		scanf("%d %d", &x, &y);
		//坐标范围合法的判断
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
    
    
			if (board[x - 1][y - 1] == ' ')
			{
    
    
				board[x - 1][y - 1] = Player_Choice;
				break;
			}
			else
			{
    
    
				printf("坐标被占用,不能下棋,请选择其他位置\n");
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入\n");
		}
	}
}

Insert image description here

2.4 Computer chess playing

In order for the computer to generate truly random numbers, we have already talked about how to do it.

void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("电脑下棋:\n");
	int x = 0;
	int y = 0;
	while (1)
	{
    
    
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = Computer_Choice;
			break;
		}
	}
}

Insert image description here

2.5 Determine winning or losing

To judge winning or losing, there are three aspects: rows, columns, and diagonals. Judgment is divided into three situations.
First determine whether the board is full.
If the board is full, 1 is returned to determine the draw and victory.
If the board is not full, 0 is returned and the game continues until the outcome is determined.

int IsFull(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;
}

We stipulate that
when the player wins, IsWinthe function returns the symbol '*',
when the computer wins, IsWinthe function returns the symbol '#',
when there is a draw, IsWinthe function returns the symbol 'Q', and
when there is no result and there is no result, IsWinthe function returns the symbol 'C'
. Therefore, IsWinthe function return type is stipulated char.

char IsWin(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];
		}
	}
	//列
	int j = 0;
	for (j = 0; j < col; j++)
	{
    
    
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
		{
    
    
			return board[1][j];
		}
	}
	//对角线
	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 'Q';
	}
	//游戏继续
	return 'C';
}

Insert image description here

2.6 game() function

game()The function is placed Test.cin . Once selected 1 开始游戏, start game()the function.
Be sure to pay attention to the logical sequence of playing chess.
After initializing the chessboard, place an "empty" element into it.
After we start playing chess, we stipulate that the player moves first and the computer moves second.
The player makes a move, determines winning or losing, displays the chessboard, and the computer makes another move, and then determines winning or losing.
There is no need to win or lose in the first round. But it doesn't hinder the game logic.

Player wins - IsWinfunction returns - Player_Choice
computer wins - IsWinfunction returns - Computer_Choice
draw - IsWinfunction returns -'Q'

void game()
{
    
    
	char result = 0;
	char board[ROW][COL] = {
    
     0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
	//下棋
	while (1)
	{
    
    
		PlayerMove(board, ROW, COL);
		//判断输赢
		result = IsWin(board, ROW, COL);

		if (result != 'C')
		{
    
    
			break;
		}
		DispalyBoard(board, ROW, COL);
		ComputerMove(board, ROW, COL);
		//判断输赢
		result = IsWin(board, ROW, COL);
		if (result != 'C')
		{
    
    
			break;
		}
		DispalyBoard(board, ROW, COL);
	}
	if (result == Player_Choice)
	{
    
    
		printf("你赢了\n");
	}
	else if (result == Computer_Choice)
	{
    
    
		printf("电脑赢了\n");
	}
	else
	{
    
    
		printf("你和电脑打成平局\n");
	}
	DispalyBoard(board, ROW, COL);
}

2.7 main() function

In fact, the main() function was written at the beginning. The author finally ended it with modification main(), so I put it at the end.
Sets the starting point for random number generation. srand((unsigned int)time(NULL));I forgot this logic. Computers produce pseudo-random numbers.
Every time you play the game, the computer is in a fixed position, which makes no sense.

int main()
{
    
    
	srand((unsigned int)time(NULL));
	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);
	return 0;
}

Insert image description here

3 Complete three-piece chess code

It mainly uses two-dimensional arrays to implement tic-tac-toe, which is mainly divided into the following three modules.
Test.cResponsible for testing the logic of the game.
Tic_Tac_Toe.cResponsible for the implementation of the game code.
Tic_Tac_Toe.hResponsible for the declaration of the game code.

3.1 Tic_Tac_Toe.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 3
#define COL 3

#define Player_Choice 'X'
#define Computer_Choice 'O'

//#define Player_Choice '√'
//#define Computer_Choice '×'

//1 初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//2 打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col);

//3 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

//4 电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);

//5 判断输赢
char IsWin(char board[ROW][COL], int row, int col);

3.2 Tic_Tac_Toe.c

#include "Tic_Tac_Toe.h"

//1 初始化棋盘
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 DispalyBoard(char board[ROW][COL], int row, int col)
//{
    
    
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
    
    
//		//打印数据
//		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
//		//打印分割信息
//		if(i<row-1)
//			printf("---|---|---\n");
//	}
//}

//2 打印棋盘
void DispalyBoard(char board[ROW][COL], int row, int col)
{
    
    
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		//打印数据
		//printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		int j = 0;
		for (j = 0; j < col; j++)
		{
    
    
			printf(" %c ", board[i][j]);
			if (j < col - 1)
				printf("|");
		}
		printf("\n");
		//打印分割信息
		//printf("---|---|---\n");
		if (i < row - 1)
		{
    
    
			int j = 0;
			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 x = 0;
	int y = 0;
	printf("玩家下棋:\n");

	while (1)
	{
    
    
		printf("请输入坐标(中间以空格分开):");
		scanf("%d %d", &x, &y);
		//坐标范围合法的判断
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
    
    
			if (board[x - 1][y - 1] == ' ')
			{
    
    
				board[x - 1][y - 1] = Player_Choice;
				break;
			}
			else
			{
    
    
				printf("坐标被占用,不能下棋,请选择其他位置\n");
			}
		}
		else
		{
    
    
			printf("坐标非法,请重新输入\n");
		}
	}
}

//4 电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
    
    
	printf("电脑下棋:\n");

	int x = 0;
	int y = 0;

	while (1)
	{
    
    
		x = rand() % row;//0~2
		y = rand() % col;//0~2
		if (board[x][y] == ' ')
		{
    
    
			board[x][y] = Computer_Choice;
			break;
		}
	}
}

//5 判断输赢
//棋盘满了就返回1
//棋盘不满返回0
int IsFull(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;
}

char IsWin(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];
		}
	}

	//列
	int j = 0;
	for (j = 0; j < col; j++)
	{
    
    
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
		{
    
    
			return board[1][j];
		}
	}
	//对角线
	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 'Q';
	}

	//游戏继续
	return 'C';
}

//返回  Player_Choice 玩家赢
//返回  Computer_Choice 玩家赢
//返回  Q 平局
//返回  C 继续


3.3 Test.c

#include "Tic_Tac_Toe.h"

void menu()
{
    
    
	printf("*****************************\n");
	printf("***********1 开始游戏*********\n");
	printf("***********0 退出游戏*********\n");
	printf("*****************************\n");
}

void game()
{
    
    
	char result = 0;
	char board[ROW][COL] = {
    
     0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);
	DispalyBoard(board, ROW, COL);
	//下棋
	while (1)
	{
    
    
		PlayerMove(board, ROW, COL);
		//判断输赢
		result = IsWin(board, ROW, COL);

		if (result != 'C')
		{
    
    
			break;
		}
		DispalyBoard(board, ROW, COL);
		ComputerMove(board, ROW, COL);
		//判断输赢
		result = IsWin(board, ROW, COL);
		if (result != 'C')
		{
    
    
			break;
		}
		DispalyBoard(board, ROW, COL);
	}
	if (result == Player_Choice)
	{
    
    
		printf("----------你赢了----------\n");
	}
	else if (result == Computer_Choice)
	{
    
    
		printf("----------电脑赢了----------\n");
	}
	else
	{
    
    
		printf("----------平局----------\n");
	}
	DispalyBoard(board, ROW, COL);
}

int main()
{
    
    
	srand((unsigned int)time(NULL));

	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);

	return 0;
}



4 Defects in game code

This computer plays chess casually. It does not use its brain. It generates random coordinates every time and does not regard us as its opponents. No vectoriality is used.
If the chessboard is larger, the computer will also know the principle of appropriateness. How much lower will the winning rate of people playing chess be?
However, it is still difficult to draw with a computer. Because it’s hard for us to lose.

Guess you like

Origin blog.csdn.net/m0_73678713/article/details/135138495