DEV Community

loading...

Reversi(Othello) game program which you can choose the first or the second in 7 lines code of C.

iigura profile image iigura ・5 min read

This article introduces a tiny Reversi(Othello) game programe which written by C in 79 characters × 7 rows. The original version of this program had been posted on 2ch which is a famous anonymous BBS in Japan for 18 years ago. Its' size was very tiny, but even "AI" routine was equipped. In the original version, players are always the first, but this time I make it to add a feature that the player can choose the first or the second under the code size limitation of 79 charcters x 7 lines.

The original code

#include <stdio.h>
int p,t,a,d,c,v,i,m[90]={0},s,r[]={-10,-9,-8,-1,1,8,9,10};void k(){if(m[p]==0)
for(i=0;i<8;i++){for(c=0,v=p+r[i];m[v]==3-t;v+=r[i])c++;if(c&&m[v]==t){a+=c;v=
p;if(d)do m[v]=t,v+=r[i];while(m[v]!=t);}}}char*h="・○●\n";int main(){for(i=
1,m[41]=m[49]=2;i<10;m[i++*9]=3)m[40]=m[50]=t=s=1;for(;;a=d=0){for(p=9;p<82;++
p)k(),printf("%.2s",&h[m[p]*2]);if(a)for(d=a=s=p=8;a==8;k())t-2?(scanf("%d %d"
,&p,&i),p+=i*9):++p;else if(s)s=0,printf("pass");else break;t=3-t;}return 0;} 

The more I read this code, the more I feel that the author of this code is a really awesome.

You can see the code at the following URL(though this page is written in Japanese):
https://pc3.5ch.net/test/read.cgi/tech/984182993/337

Improved version

int printf(const char*,...);int scanf(const char*,...);int p,t,a,d,c,v,i,m[90]
,s,r[]={-10,-9,-8,-1,1,8,9,10};char h[]=" - x x\n";void k(){if(m[p]==0)for(i=0
;i<8;i++){for(c=0,v=p+r[i];m[v]==3-t;v+=r[i])c++;if(c&&m[v]==t){a+=c;v=p;if(d)
do m[v]=t,v+=r[i];while(m[v]-t);}}}int main(int q,char**z){t=q;h[2*t+1]='o';f\
or(i=1,m[41]=m[49]=2;i<10;m[i++*9]=3)m[40]=m[50]=s=1;for(;;a=d=0){for(p=9;p<82
;++p)k(),printf("%.2s",h+m[p]*2);if(a)for(d=a=s=p=8;a==8;k())t-2?scanf("%d %d"
,&p,&i),p+=i*9:++p;else if(s)s=0,printf("pass");else break;t=3-t;}return 0;}

If you execute without arguments, the player becomes the first. When you run with one argument, such as ./a.out aaa, the player will be second. In this program, there is no argument or only one argument is supported. Please do not execute with more than two arguments.

The state of actual execution is as follows. Please enter the column and row number with separate by the space. The upper left is 1 1 and the lower right is 8 8.

$ ./a.out

 - - - - - - - -
 - - - - - - - -
 - - - - - - - -
 - - - o x - - -
 - - - x o - - -
 - - - - - - - -
 - - - - - - - -
 - - - - - - - -
5 3

 - - - - - - - -
 - - - - - - - -
 - - - - o - - -
 - - - o o - - -
 - - - x o - - -
 - - - - - - - -
 - - - - - - - -
 - - - - - - - -

 - - - - - - - -
 - - - - - - - -
 - - - x o - - -
 - - - x o - - -
 - - - x o - - -
 - - - - - - - -
 - - - - - - - -
 - - - - - - - -

Commentary

The way for the player to become the second

Since variable t is having the information of turns, if t=2 at the start of the game, the computer become the first. Specifically, it suffices to change to t=2 at the beginning of the 'main' function.

m[40]=m[50]=t=s=1;    /* before */
m[40]=m[50]=s=1,t=2;  /* after  */

Changing player's piece character

By above modification, it is now possible to choose the first and the second. But the player's piece character is always 'o' regardless of the order as it is. Let's change this. The character of the piece is defined by the variable h, then it is sufficient to modify the contents of h appropriately.

Specifically, when player is the first, that is, at t=1, it is sufficient to set h[3]='o' and h[5]='x', and when the other case, that is, at t=2, it is sufficient to set h[3]='o' and h[5]='x', too.

Both setting 'o' and 'x' respectively, the amount of the code will increase. So beforehand it set h[3] and h[5] to 'x' and change h[3] or h[5] to 'o' according to the value of t.

char h[]=" - x x\n";
h[2*t+1]='o';

The type of variable h has changed from char* to char[]. This is because, in case of char* , to changing character of h, it means that it will be changes the constant character string. So the resulting in memory access violation error occured and the program will be terminated.

How to specify the first or the second

"Are you the first? or the second?" If a program are wrote that asks you as usual using printf and scanf, it may not to fit in 7 lines. So, use the arguments on the command line to specify the first or the second. If you want to play as the first player, please execute this othello program with no arguments. Or, if you would be the second player, please execute this with one argument. Of course, the command line argument for the program is anythig fine. The important things is number of arguments. Not an arguments contents.

Then the program will be as follows:

int main(int q,char**z){t=q; ... }

On this code, the number of arguments is once stored in a variable 'q'. It is because that the variable 't' at the main() function first argument, it seems to become a const int (on Apple LLVM version 10.0.0 (clang-1000.11.45.5), gcc / macOS mojave).

Excavation of the blanks

The strategy for the improvement has done, so we have to find the blanks to add them. In the original code, there is no large space other than the first line. However, the #include directive needs to be written from the beginning of the line, and it is not allowed to write any program after that.

Let's think why is the original code also including stdio.h in the first place? That is of course because that the prototype declarations of the printf and the scanf are necessary. The first line can be changed as follows:

#include <stdio.h>  // before

int printf(const char*,...);int scanf(const char*,...);  // after

With this change, we were able to get 23 blank spaces!

Little by little, let's further shorten the code and let's make more blanks:

m[90]={0},  // before
m[90],      // after   ( get 4 spaces )

while(m[v]!=t);  // before
while(m[v]-t);   // after   ( get a space )

printf("%.2s",&h[m[p]*2]);  // before
printf("%.2s",h+m[p]*2);    // after   ( get 2 spaces )

And, we will continue to use continuation lines so that we can line break in the middle of keywords.

// like this
f\
or

Summary

Finally, modified code will be pushed into the margin made like this. due to a line feed position, it replaced the order of the part of the program. However the meaning of the program code has not changed.

Discussion (0)

Forem Open with the Forem app