The most classic language makes the most classic game ゚ヽ(。◕‿◕。)ノ゚.:。+ ゚

Posted by papacostas on Sun, 30 Jan 2022 09:54:46 +0100

Gobang 2.0 coming: ゚ヽ(。◕‿◕。)ノ゚.:

Function overview:

  1. It can realize man-machine combat
  2. Everyone can fight
  3. You can surrender and count the game time

Compared with the previous Gobang, the core algorithm has not changed. It still judges whether there are five sub lines in the current state (in four directions) of each chess piece. If there are five sub lines, you can directly judge the current game situation.

Well, don't say much, just go to the code (´ ・ ω ・`)

The first is the function declaration and macro definition:

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
#define hang 18 / / the defined chessboard has 18 rows and 18 columns
#define lie 18
void menu(void);
void Init(void);
void Drawmap(void);
int Judge(int x,int y);
void Computer_game(void);
void Player_game(void);
char map[hang][lie];  //Use a two-dimensional array to represent the chessboard

Next are initialization functions and map printing functions:

void Init(void)
{
	int i,j;
	for(i=4;i<hang-4;i++)
	{
		for(j=4;j<lie-4;j++)
		{
			map[i][j]=' '; //In initialization, set the falling point of each piece in each chessboard to be empty
		}
	}
}

void Drawmap(void)
{
	int i,j;
	printf("0      ");
	for(i=4;i<lie-8;i++)
	{
		printf("%d  ",i);
	}
	for(i=10;i<lie-4;i++)
	{
		printf("%d ",i);
	}
	printf("\n");
	printf("\n");
	printf("\n");
	printf("\n");
	for(i=4;i<hang-8;i++)
	{
		printf("%d      ",i);
		for(j=4;j<lie-4;j++)
		{
			printf("%c  ",map[i][j]);
		}
		printf("\n");
	}
	for(i=10;i<hang-4;i++)
	{
		printf("%d     ",i);
        for(j=4;j<lie-4;j++)
		{
            printf("%c  ",map[i][j]);
		}
        printf("\n");
	}		
}

Don't forget to add serial numbers here, including horizontal serial numbers and vertical serial numbers. There is a problem about array out of bounds.
Because to judge the current state of each chess piece in four directions, it will involve the bottom problem. If the set two-dimensional array can just store all the current pieces, the array will cross the boundary when judging, that is, when the pieces are at the top or bottom, the judged area is not included in the array.
For example, when the chess pieces are located at (0,0), if you want to judge the four horizontal chess pieces, you will obviously judge (0, - 1) and (0, - 2), but there is no - 2 column at all, so this will be a big problem and the program may crash.
Then someone will say at this time: my array is out of bounds, isn't it still running well?
Then I think this explanation is more vivid:

By train, you bought a station ticket / (ㄒ o ㄒ)/~~
But you're lucky. You find a seat that's just empty
So you took a try and sat in that position, thinking that you could just sit for a while, but you were lucky enough to get off at the terminal

In other words, the address of the part of your array that crosses the boundary is not used by other programs, so it runs normally. This is generally a small program. If it is a large program, it is easy to crash or BUG.

After knowing that the array is out of bounds, we can easily understand the practice of setting a larger range of arrays. So let's continue:
Judgment function (core function):

int Judge(int x,int y)
{
	if(map[x][y]==map[x+1][y+1]&&map[x][y]==map[x+2][y+2]&&map[x][y]==map[x+3][y+3]&&map[x][y]==map[x+4][y+4])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y-1]&&map[x][y]==map[x+1][y+1]&&map[x][y]==map[x+2][y+2]&&map[x][y]==map[x+3][y+3])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][x-1]&&map[x][y]==map[x-2][y-2]&&map[x][y]==map[x+1][y+1]&&map[x][y]==map[x+2][y+2])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y-1]&&map[x][y]==map[x-2][y-2]&&map[x][y]==map[x-3][y-3]&&map[x][y]==map[x+1][y+1])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y-1]&&map[x][y]==map[x-2][y-2]&&map[x][y]==map[x-3][y-3]&&map[x][y]==map[x-4][y-4])
	{
		return 1;
	}
	if(map[x][y]==map[x+1][y-1]&&map[x][y]==map[x+2][y-2]&&map[x][y]==map[x+3][y-3]&&map[x][y]==map[x+4][y-4])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y+1]&&map[x][y]==map[x+1][y-1]&&map[x][y]==map[x+2][y-2]&&map[x][y]==map[x+3][y-3])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y+1]&&map[x][y]==map[x-2][y+2]&&map[x][y]==map[x+1][y-1]&&map[x][y]==map[x+2][y-2])
	{
		return 1;
	}
	if(map[x][y]==map[x+1][y-1]&&map[x][y]==map[x-1][y+1]&&map[x][y]==map[x-2][y+2]&&map[x][y]==map[x-3][y+3])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y+1]&&map[x][y]==map[x-2][y+2]&&map[x][y]==map[x-3][y+3]&&map[x][y]==map[x-4][y+4])
	{
		return 1;
	}
	if(map[x][y]==map[x][y+1]&&map[x][y]==map[x][y+2]&&map[x][y]==map[x][y+3]&&map[x][y]==map[x][y+4])
	{
		return 1;
	}
	if(map[x][y]==map[x][y-1]&&map[x][y]==map[x][y+1]&&map[x][y]==map[x][y+2]&&map[x][y]==map[x][y+3])
	{
		return 1;
	}
	if(map[x][y]==map[x][y-2]&&map[x][y]==map[x][y-1]&&map[x][y]==map[x][y+1]&&map[x][y]==map[x][y+2])
	{
		return 1;
	}
	if(map[x][y]==map[x][y-3]&&map[x][y]==map[x][y-2]&&map[x][y]==map[x][y-1]&&map[x][y]==map[x][y+1])
	{
		return 1;
	}
	if(map[x][y]==map[x][y-4]&&map[x][y]==map[x][y-3]&&map[x][y]==map[x][y-2]&&map[x][y]==map[x][y-1])
	{
		return 1;
	}
	if(map[x][y]==map[x+1][y]&&map[x][y]==map[x+2][y]&&map[x][y]==map[x+3][y]&&map[x][y]==map[x+4][y])
	{
		return 1;
	}
	if(map[x][y]==map[x-1][y]&&map[x][y]==map[x+1][y]&&map[x][y]==map[x+2][y]&&map[x][y]==map[x+3][y])
	{
		return 1;
	}
	if(map[x][y]==map[x-2][y]&&map[x][y]==map[x-1][y]&&map[x][y]==map[x+1][y]&&map[x][y]==map[x+2][y])
	{
		return 1;
	}
	if(map[x][y]==map[x-3][y]&&map[x][y]==map[x-2][y]&&map[x][y]==map[x-1][y]&&map[x][y]==map[x+1][y])
	{
		return 1;
	}
	if(map[x][y]==map[x-4][y]&&map[x][y]==map[x-3][y]&&map[x][y]==map[x-2][y]&&map[x][y]==map[x-1][y])
	{
		return 1;
	}
	return 0;
}

There are 20 possibilities to judge whether the next chess piece forms a line of five pieces with other chess pieces in other directions. Don't forget the position of the most central point. It doesn't coincide, and it comes from the judgment in four directions. If there are five sub lines, return 1. If there is no five sub lines, return 0. It's easy to understand here.

Man machine Combat:

void Computer_game(void)
{
	int start,end;
	int x,y,x0,y0,n=0;
	Init();
	start=clock();
	while(1)
	{
		system("cls");
		Drawmap();
		printf("Please enter your coordinates(Row, column):\n");
		scanf("%d%d",&x,&y);
		if(x<4||x>13||y<4||y>13||map[x][y]!=' ')
		{
			printf("Your coordinates are illegal, please try to re-enter...\n");
			system("pause");
			continue;
		}
		else
		{
			map[x][y]='X';
			n++;
		}
		while(1)
		{
			srand(time(NULL));
			x0=rand()%10+4;
			y0=rand()%10+4;
			if(map[x0][y0]!=' ')
			{
				continue;
			}
			else
			{
				map[x0][y0]='O';
				n++;
				break;
			}
		}
		if(Judge(x,y)==1)
		{
			system("cls");
			Drawmap();
			printf("Player wins!\n");
			end=clock();
			printf("The time spent by this bureau is%d second...\n",(end-start)/1000);
			system("pause");
			break;
		}
		if(Judge(x0,y0)==1)
		{
			system("cls");
			Drawmap();
			printf("Computer wins!\n");
			end=clock();
			printf("The time spent by this bureau is%d second...\n",(end-start)/1000);
			system("pause");
			break;
		}
		if(n==100)
		{
			system("cls");
			Drawmap();
			printf("it ends in a draw!\n");
			end=clock();
			printf("The time spent by this bureau is%d second...\n",(end-start)/1000);
			system("pause");
			break;
		}
	}
}

The core of man-machine combat is still srand function and rand function. The disadvantages are obvious. As time is the seed, the result is that the computer is as stupid as a pig. The advantage is that it is convenient and easy. Of course, you can insert an algorithm into the computer, so that the computer has a variety of paths to choose and take the optimal path, but this method is more complex and has obvious advantages, which makes the computer have a thinking mode and makes the game challenging.

The internal implementation of rand() is realized by linear congruence method. It is a pseudo-random number. Due to the long period, it can be regarded as random in a certain range.
The rand function requires the srand() function to set the random number seed when rand() generates random numbers.
The parameter seed is an integer. You can usually use the return value of time(0) or getpid(0) as seed.

Everyone fights:

void Player_game(void)
{
	char name1[20];
	char name2[20];
	int x1,y1,x2,y2,n=0;
	int start,end;
	printf("Please enter the nickname of player 1:\n");
	scanf("%s",name1);
	printf("Please enter the nickname of player 2:\n");
	scanf("%s",name2);
	Init();
	start=clock();
	while(1)
	{
		system("cls");
		Drawmap();
		printf("please %s Enter coordinates(Row, column): Enter coordinates(0,0)surrender\n",name1);
		scanf("%d%d",&x1,&y1);
		if(x1==0&&y1==0)
		{
			goto w2;
		}
        if(x1<4||x1>13||y1<4||y1>13||map[x1][y1]!=' ')
		{
			printf("The coordinates you entered are illegal. Please try to enter again...\n");
			system("pause");
			continue;
		}
		else
		{
			map[x1][y1]='X';
			n++;
		}
		system("cls");
		Drawmap();
		if(Judge(x1,y1)==1)
		{
w1:
			system("cls");
			Drawmap();
			printf("%s win victory!\n",name1);
			end=clock();
			printf("The time spent by this bureau is%d second...\n",(end-start)/1000);
			system("pause");
			break;
		}
		printf("please %s Enter coordinates(Row, column): Enter coordinates(0,0)surrender\n",name2);
		scanf("%d%d",&x2,&y2);
		if(x2==0&&y2==0)
		{
			goto w1;
		}
        if(x2<4||x2>13||y2<4||y2>13||map[x2][y2]!=' ')
		{
			printf("The coordinates you entered are illegal. Please try to enter again...\n");
			system("pause");
			continue;
		}
		else
		{
			map[x2][y2]='O';
			n++;
		}
		if(Judge(x2,y2)==1)
		{
w2:
			system("cls");
			Drawmap();
			printf("%s win victory!\n",name2);
			end=clock();
			printf("The time spent by this bureau is%d second...\n",(end-start)/1000);
			system("pause");
			break;
		}
		if(n==100)
		{
			system("cls");
			Drawmap();
			printf("it ends in a draw!\n");
			end=clock();
			printf("The time spent by this bureau is%d second...\n",(end-start)/1000);
			system("pause");
			break;
		}
	}
}

Here, the method of entering nickname is used to determine the player. At the same time, the current player's decision to surrender can be judged according to (0,0) to end the game.
The other aspect is to make rational use of the judge function. Here we emphasize that the position of the judgment function is very important. You can't put two judgment functions together. You should make a judgment immediately after a player completes the placement, otherwise there will be a situation where one party has five children connected and the other party can still continue to play chess. At the same time, the start and end variables are used for timing.

Menu function:

void menu(void)
{
	printf("============================================\n");
	printf("============================================\n");
	printf("===============Gobang Gobang=================\n");
	printf("============================================\n");
	printf("================1.Man machine combat==================\n");
	printf("============================================\n");
	printf("================2.Player battle==================\n");
	printf("============================================\n");
	printf("================3.Exit the game==================\n");
	printf("============================================\n");
	printf("============================================\n");
}

main function:

int main(void)
{
	char choice,c;
	system("color 2");
	while(1)
	{
p:
		system("cls");
		menu();
		printf("Please enter your choice:\n");
		scanf(" %c",&choice);
		if(choice=='1')
		{
			Computer_game();
			break;
		}
		else if(choice=='2')
		{
			Player_game();
			break;
		}
		else if(choice=='3')
		{
			printf("Exiting the game......\n");
			Sleep(1200);
			return 0;
		}
		else
		{
			printf("Input error, please try to input again...\n");
			continue;
			break;
		}
	}
	printf("Continue the game?(Y/N)\n");
	scanf(" %c",&c);
	if(c=='y'||c=='Y')
	{
		goto p;
	}
	return 0;
}

The main function is a process of allocating functions.
Because it's Gobang, I don't archive, just timing. Archiving is also very simple. It can be done through fopen function. I won't repeat it here.
There are no warnings and errors in the operation, and no bugs are found at present.
Even if it is completely over here, the division of labor of each section is clear. Welcome to give your opinions and help me correct it. Thank you (づづづづづづづづづづづづづづづづづ

Topics: C Algorithm Mini Program Game Development