connect four is a game. there is a grid. the grid has 7 columns and 6 rows. there are two players. each has a colour of piece they put on the grid. they take turns making moves.
to make a move, you pick a non-full column and put a piece of your colour on the lowest empty space on that column. if you form a diagonal, vertical or horizontal line of
4 pieces of your colour, you win the game. otherwise, the next person plays. if the grid is full, the game is a tie.
the interface is simple. your program starts. it reads either an s or an f from stdin, followed by a newline.
if the character was s, it goes second. it reads an ascii digit from 1 to 7 from stdin, followed by a newline. it updates its internal state to reflect that the other player has played this move. the program continues to run.
it writes an ascii digit from 1 to 7 to stdout, followed by a newline. the program continues to run. it reads another move and continues ad infinitum. once the game is over, any further behaviour is not specified.
if the character was f, it goes first. it writes an ascii digit from 1 to 7 to stdout, followed by a newline. this represents its first move. the following behaviour is the same as s.
the newlines are required in the hopes that they will make buffering work correctly, as streams should be line-buffered by default. they are very important. do not forget to include and read them.
your challenge is to implement such a program. your program must be executable from an environment with standard io streams and have the exact interface as described above.
it does not have to play connect four optimally. it only has to play. all moves output must be valid. all moves received will be valid. there is no otherwise. otherwise is undefined.
importControl.Monad;main=getLine>>=(`when`putStrLn"1").("f"==)>>interact(unlines.(++[""]).fmap(show.succ.(`mod`7).read).lines)-- breaks when enemy s plays x=7, y=6
// Copyleft 2007-2023 <redacted>// To compile: `gcc connect-four.c -o connect-four`#include<stdlib.h>#include<math.h>#include<stdio.h>#include<stdbool.h>#include<time.h>typedefstructVec2{intx;inty;}Vec2;intbroad[7][6];#define WIN_DRAW -1#define WIN_TBA 0#define WIN_PLAYER 1#define WIN_COMPUTER 2boollooping=true;intwin=WIN_TBA;voiddramaticExit(){for(size_ti=0;i<420;i++){printf("WHAT?????????????????????????");}intlol=423;printf(lol);// BOOM}voiddrawboard(){system("clear");for(inti=5;i>-1;i--){for(intj=0;j<7;j++){if(broad[j][i]==1){printf("| X ");}elseif(broad[j][i]==2){printf("| O ");}elseif(broad[j][i]==3){printf("|@@@");}else{printf("| ");}}printf("|");printf("\n+---+---+---+---+---+---+---+\n");}}intsterilize(charcar){switch(car){case'1':return1;case'2':return2;case'3':return3;case'4':return4;case'5':return5;case'6':return6;case'7':return7;case10:return-1;default:dramaticExit();break;}}boolcheckfilled(){for(inti=5;i>-1;i--){for(intj=0;j<7;j++){if(broad[j][i]){returnfalse;}}}win=WIN_DRAW;returntrue;}boolchecksuccess(intx,inty,intindividual){boolprevhad=false;intstreamlen;for(inti=0;i<7;i++){if(!prevhad)streamlen=0;prevhad=(broad[i][y]==individual);if(prevhad){streamlen++;if(streamlen>=4)returntrue;}}prevhad=false;for(inti=0;i<6;i++){if(!prevhad)streamlen=0;prevhad=(broad[x][i]==individual);if(prevhad){streamlen++;if(streamlen>=4)returntrue;}}prevhad=false;Vec2temp={x,y};while(true){if(temp.x==0||temp.y==0){break;}temp.x--;temp.y--;}for(inti=0;i<420;i++){if(!prevhad)streamlen=0;if(temp.x+i>7||temp.y+i>6){break;}prevhad=(broad[temp.x+i][temp.y+i]==individual);if(prevhad){streamlen++;if(streamlen>=4)returntrue;// COOL}}prevhad=false;temp.x=x;temp.y=y;while(true){if(temp.x==6||temp.y==0){break;}temp.x++;temp.y--;}for(inti=0;i<99;i++){if(!prevhad)streamlen=0;if(temp.x+i<0||temp.y+i>6){// HMMbreak;}prevhad=(broad[temp.x-i][temp.y+i]==individual);if(prevhad){streamlen++;if(streamlen>=4)returntrue;}}returnfalse;}Vec2place(intchoice){if(choice==-1){// BRUHdramaticExit();}inthasplaced=0;for(inti=0;i<6;i++){if(broad[choice-1][i]==0){broad[choice-1][i]=1;Vec2pos={choice-1,i};returnpos;}}}Vec2artificialstupidity(){while(true){intaichoice=(rand()%6)+1;for(inti=0;i<6;i++){if(broad[aichoice-1][i]==0){broad[aichoice-1][i]=2;Vec2pos={aichoice-1,i};returnpos;}}}}intcool(){srand(time(NULL));for(inti=0;i<7;i++){for(intj=0;j<6;j++){broad[i][j]=0;}}charcar,intro;intchoice;boolplayersuccess,aisuccess;printf(" βββββββ βββββββ ββββ βββ βββ βββ\n");printf("ββββββββββββββββββββββ βββ βββ βββ\n");printf("βββ βββ βββββββββ βββββββββββββββββ\n");printf("βββ βββ βββββββββββββββββββββββββββ\n");printf("ββββββββββββββββββββ ββββββ βββ\n");printf(" βββββββ βββββββ βββ βββββ βββ\n");printf("==--==--==--==--==-==--==--==--==--==--==\n");printf("Select if you wan to go first or secoond:\n");// can i haz charintro=getchar();// artificial stupidity takes one for the teamif(intro=='s'){Vec2aipos=artificialstupidity();}while(win==WIN_TBA){drawboard();car=getchar();choice=sterilize(car);if(choice!=-1){Vec2placepos=place(choice);playersuccess=checksuccess(placepos.x,placepos.y,1);if(playersuccess){win=WIN_PLAYER;drawboard();break;}checkfilled();Vec2aipos=artificialstupidity();aisuccess=checksuccess(aipos.x,aipos.y,2);if(aisuccess){win=WIN_COMPUTER;drawboard();break;}checkfilled();}}switch(win){caseWIN_DRAW:printf("Nobody won... Thanks for playing.\n");returnWIN_DRAW;caseWIN_PLAYER:printf("You won... Thanks for playing.\n");returnWIN_PLAYER;caseWIN_COMPUTER:printf("Computer won... Thanks for playing.\n");returnWIN_COMPUTER;}}intmain(void){/*#ifndef _WIN32 // I change my mind, but windows cool printf("please install install windows 10: \n"); printf("https://www.microsoft.com/de-de/software-download/windows10ISO"); return 69;#else*/intret=cool();/*#endif*/returnret;}
hwβ67gpβgmβhwβ΄0positionsβ{hwββΊβabβΒ―1+β΄β΅β,[β³2](1-β³w-b)β½β€099β’(1-β³h-a)ββ€099β’hwββ΅}graβββͺ/hwβpositionsΒ¨(,β₯ββββ¨14β΄1),(,β₯βββ½β¨β.=β¨β³4)movecolβ{gpgmββ΅β(gpβ gm)(β(-β€β΄β,β1)@βΊβgm)}dispβ{'.βΊβ'[β1++βΏβ΅]}invββ(β ,β₯ββ’)/threatsβ{gpgmββ΅ββΊβhwβ΄0βgraβΏβ¨~graβ¨/β€,β€β§β€2β’βΊβ¨gpβ gm}ruleβ{sββΊβ΅β΅β€299β€992β’bβββΊβΊ/β΅β(β¨/s)ββΏΒ¨sb}claimevenβ{mβ2βΏβ€2β’(hΓ·2)wpositions11β΄1β each possible positionmβΏβ¨~mβ¨/β€,β€β§β€2β’β΅β keep valid ones}rule(β¨/β€,(βwhβ΄2|β³h)β§β§)β threats solved, (ββ΄b)(ββ΄βΊ)β‘β΄xbaseinverseβ{(,β.<β¨β³w)βΏ,[β³2]+β€992β€299β¨β’132β(β.=β¨β³w)β.Γβ€1(2</,β1)ββ΅}rule(2=+/β€,β€β§)verticalβ{mβ(Β―1βhβ2βΏβ’)β€2β’(Β―1+hΓ·2)wpositions11β΄1mβΏβ¨~mβ¨/β€,β€β§β€2β’β΅}rule(2=+/β€,β€β§)afterevenβ{mβ((-h)β2|β³h-2)ββ€2β’(Β―1+hΓ·2)wpositions14β΄1ββ€(β¨ββ€ββ΅<β’)β€2β’mβΏβ¨(βΊββ§β±β₯(β¨/,)β΅β§Β―1ββ΅<β’)β€2β’m}rule(β’β‘β₯(β¨βΏ)β§)tableββ1table,ββ11table,ββ111table,ββ1113table,ββ211124table,ββ2111244table,ββ111112121table,ββ1113231213table,ββ11132312133tableβ(β’ββ)βtablepairableβ{abββ΅βΊ=1:β§/,aβ²bβΊ=3:β§/a(β§/β€β²β¨β‘β€1)β₯βbβΊ=13:(pairableβ1β§pairableβ3)ab}evalβ{βΊβhwβ΄0rulesβ{(βΊclaimevenβ΅)(βΊbaseinverseβ΅)(βΊverticalβ΅)(βΊafterevenβ΅)}slvssqrstypsβ(βͺβΏ,ββββΈ(β’Β¨β’/))ββΊ(threatsrulesβ’)β΅slvssqrstypsβ(~βΊβ¨/β€,β€β§β€2β’sqrs)ββΏΒ¨slvssqrstyps0=β’slvs:0confβ~(β.(β·βtableβ€,)β¨typs)pairableΒ¨(β,β₯β)β€299β€992β¨sqrsconfthingslvs}thingβ{βββ΄Β¨βΊβ΅β βΊ:CONFlict(rulesΓrules) β΅:SoLVeS(rulesΓthreats)0=β’/β΄β΅:1β no threats~β¨/mββ΅[;ββ+βΏβ΅]:0β m: mask of rules that solve hardest threatrtβ~(β¨βΏmββΏ)Β¨βΊβ΅β remove rules/threats solved by m (r/βΊ)ββ₯(rββΏ)t/β΅}oddthreatβ{tβthreatsinv(gpgmββ΅)uβtβΏβ¨3=t+/β€,β€β§β€2β’gpβ gmβ unsure why i need this, copied from somewhere elsebtmβ(-β€β΄ββͺβ0)ββ¨βββ¨βΏ(2<βΏ0ββͺ)β€2threatsβ΅ββ¨βββ¨βΏbtm<β€2β’(2<βΏ1βͺβ¨gm)<β€2β’(βwhβ΄2|β³h)<β€2β’u>β€2β’gpβ gm}eval2β{β /,2ββ΅:{β¨/,otβoddthreatβ΅:otevalβ΅β0}β΅β-evalβ΅}abβ{abββΊ0β vβeval2β΅:vmovesβ(movecolββ΅Β¨β³w)~βinvβ΅β /,2ββ΅:Β―1a{vaββΊ0=β’β΅:vb<uβvβababββ΅:uu(uβa)β1ββ΅}moves1b{vbββΊ0=β’β΅:vb<uβvβababββ΅:uu(uβb)β1ββ΅}moves}{ββββ’?7ββ0}0
importosimportosprocimportstd/strutilsimportstd/streamstypeSpot=enumFree,Ours,TheirsStack=array[6,Spot]Board=array[7,Stack]varboard:Boardvarwinner:Spot=FreeprocprintBoard=forrowincountdown(5,0):forcolin0..6:constspotChar:array[Spot,char]=['.','O','X']stdout.writespotChar[board[col][row]]stdout.write'\n'stdout.flushFile()procinvalidMove(move:uint):bool=move<1ormove>7orboard[move-1][^1]!=FreeprocinBounds(x,y:int):bool=x>=0andx<7andy>=0andy<6proccountDir(x,y:uint,dx,dy:int):uint=varcount:uint=0varx=int(x)vary=int(y)letexpected=board[x][y]whiletrue:x+=dxy+=dyifnotinBounds(x,y)orboard[x][y]!=expected:breakcount+=1returncountproccheckWinDir(x,y:uint,dx,dy:int):bool=returncountDir(x,y,-dx,-dy)+1+countDir(x,y,dx,dy)>=4proccheckWin(x,y:uint):bool=checkWinDir(x,y,0,1)orcheckWinDir(x,y,1,0)orcheckWinDir(x,y,1,1)varmoves=0procmakeMove(move:uint,player:Spot)=assertplayer!=Freefory,spotinboard[move]:ifspot==Free:board[move][y]=playerifcheckWin(move,uint(y)):winner=playermoves+=1breakvarbot=startProcess(paramStr(1),options={})varbotIn=bot.inputStreamvarbotOut=bot.outputStreamprocsendCommand(command:string)=botIn.writeLinecommandbotIn.flushsendCommand"s"# hoomans go first!whiletrue:printBoard()ifwinner!=Freeormoves==6*7:breakblock:echo"Make a move:"letmove=stdin.readLine.parseUIntifinvalidMove(move):echo"Invalid move"continuemakeMove(move-1,Ours)sendCommand$moveifwinner==Free:varline:stringassertbotOut.readLinelineletmove=line.parseUIntifinvalidMove(move):echo"Invalid move from bot"break# can't resume with a broken botmakeMove(move-1,Theirs)bot.terminatebot.closeconstoutcome:array[Spot,string]=["Draw","You win!","They win!"]echooutcome[winner]
importtimeimportrandomfrommultiprocessing.shared_memoryimportShareableListdefget_or_create(name):try:returnShareableList(name=name)except:returnShareableList(sequence=[0]+[b"-"*256]*256,name=name)defplay_random_move(heights):o=random.choice([ifori,xinenumerate(heights,start=1)ifx!=6])heights[o-1]+=1print(o)defplay_randomly(go_first):"""Boring agent used as a fallback when we can't find a partner (me irl)"""heights=[0]*7ifgo_first:play_random_move(heights)whileTrue:i=int(input())heights[i-1]+=1play_random_move(heights)firsts=get_or_create("cg45_hair_firsts")seconds=get_or_create("cg45_hair_seconds")are_first=input()=="f"theirs,ours=(firsts,seconds)ifare_firstelse(seconds,firsts)ifnottheirs[0]:channel=ShareableList([None])ours[1+ours[0]]=channel.shm.nameours[0]+=1for_inrange(10):time.sleep(0.5)ifchannel[0]:breakelse:play_randomly(are_first)channel[0]=Noneelse:theirs[0]-=1channel=ShareableList(name=theirs[theirs[0]+1])channel[0]=1whilechannel[0]isnotNone:passdefplay_move():whilechannel[0]isNone:passprint(channel[0])channel[0]=Noneifare_first:play_move()whileTrue:channel[0]=int(input())whilechannel[0]isnotNone:passplay_move()
packagejeu;publicclassCase{charnature;/** * Constructeur de Case * * @param nature_ */Case(charnature_){this.nature=nature_;}/** * get la nature d'une case * * @return nature de la case */publicchargetNature(){returnthis.nature;}/** * Permet de donner/changer la nature d'une case * * @param nat la nature Γ donner */publicvoidsetNature(charnat){this.nature=nat;}}
packagejeu;publicclassConversion{/** * Retourne le char d'une case en String (ex: A10 --> A) * * @param caseEnString la case en String * @return x le char de la case */publicchargetCharFromString(StringcaseEnString){charx=' ';if(caseEnString.length()==2){x=caseEnString.charAt(0);}elseif(caseEnString.length()==3){x=caseEnString.charAt(0);}returnx;}/** * Retourne l'entier d'une case en String (ex: A10 --> 10) * * @param caseEnString la case en String * @return y */publicintgetIntFromString(StringcaseEnString){inty=0;if(caseEnString.length()==2){y=Integer.parseInt(caseEnString.substring(1));}elseif(caseEnString.length()==3){y=Integer.parseInt(caseEnString.substring(1,3));}returny;}publicvoidformatCoupJoues(Stringcoord1,Stringcoord2,Stringnom,Stringnom2){Stringindent=" ";// 20 spaces.intl;intadd1=nom.length()/2;intadd2=nom2.length()/2;if(nom.length()==1){nom=" "+nom+indent.charAt(0);add1=1;}elseif(nom.length()==2){nom+=indent.charAt(0);}l=nom2.length();nom2=" "+nom2;if(l==1){nom2+=" |";add2=1;}elseif(l==2){nom2+=indent.substring(0,2)+"|";}else{nom2+=" |";}l=coord1.length();coord1=indent.substring(0,add1)+coord1+indent.substring(0,add1);if(l==2){coord1+=" ";}l=coord2.length();coord2=indent.substring(0,add2)+coord2+indent.substring(0,add2);if(l==2){coord2+=" ";}System.out.println("| "+nom+" |"+nom2);System.out.println("|"+coord1+"|"+coord2+"|\n");}}
packagejeu;importjava.util.ArrayList;importjava.util.Random;publicclassIA{finalStringname;privatefinalRandomrandom=newRandom();/** * Le constructeur de la classe IA * * @param name_ le nom de l'IA */IA(Stringname_){this.name=name_;}/** * Renvoie le nom de l'IA * * @return le nom de l'IA */publicStringgetName(){returnthis.name;}/** * Permet Γ l'IA de jouer un coup choisi au hasard choisi parmi les coups possibles * * @param coupsPossibles la liste des coups possibles * @return un coup choisi au hasard */publicCasejoueUnCoupRandom(ArrayList<Case>coupsPossibles){returncoupsPossibles.get(random.nextInt(coupsPossibles.size()));}}
#include<cstddef>#include<iostream>#include<limits>#include<memory>#include<stdexcept>#include<string>#include<type_traits>#include<utility>enumclassColor{None=0,White=1,Black=2,};Coloropposite(Colorcolor){returncolor==Color::White?Color::Black:Color::White;}classBoard{staticconstexprautotransposition_table_size=2<<10;staticconstexprautowin_score=10000;ColorcurrentColor;intheight[7];Colorgrid[7][6];structTransposition{boolvalid;intscore;std::size_thash;};std::unique_ptr<Transposition[]>transposition_table;public:Board():height{},grid{{Color::None}},currentColor{Color::White}{transposition_table=std::make_unique<Transposition[]>(transposition_table_size);}intget_best_move(){intbestColumn=0;intbestScore=-win_score;for(intcolumn=0;column<7;++column){if(height[column]==6){continue;}drop(column);intscore=is_win(opposite(currentColor),column,height[column]-1)?win_score:-negamax(6,-win_score,win_score);undrop(column);if(score>bestScore){bestColumn=column;bestScore=score;}}returnbestColumn;}voiddrop(intcolumn){auto&columnHeight=height[column];if(columnHeight>=6){throwstd::runtime_error{"Attempted to drop a tile on a full column"};}grid[column][columnHeight]=currentColor;currentColor=opposite(currentColor);++columnHeight;}voidundrop(intcolumn){auto&columnHeight=height[column];--columnHeight;grid[column][columnHeight]=Color::None;currentColor=opposite(currentColor);}intnegamax(intdepth,intalpha,intbeta){autoconsthash=state_hash();auto&entry=transposition_table[hash%transposition_table_size];if(entry.valid&&entry.hash==hash){returnentry.score;}if(depth<0){returneval();}for(intcolumn=0;column<7;++column){if(height[column]==6){continue;}drop(column);intscore=is_win(opposite(currentColor),column,height[column]-1)?win_score:-negamax(depth-1,-beta,-alpha);undrop(column);if(score>beta){returnbeta;}if(score>alpha){alpha=score;}}entry.valid=true;entry.hash=hash;entry.score=alpha;returnalpha;}inteval(){returnadvantage(currentColor)-advantage(opposite(currentColor));}intadvantage(Colorcolor){inttotal=0;for(intcolumn=0;column<7;++column){intcount=0;for(introw=height[column]-1;row>=0&&grid[column][row]==color;--row){++count;}total+=count;}returntotal;}boolis_win(Colorcolor,intcolumn,introw){std::pair<int,int>deltas[]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1},};for(autoconst&[deltaX,deltaY]:deltas){for(intoffset=0;offset<4;++offset){autoconstoffsetColumn=column+deltaY*offset;autoconstoffsetRow=row+deltaX*offset;if(offsetColumn<0||offsetColumn>=7||offsetRow<0||offsetRow>=6||grid[offsetColumn][offsetRow]!=color){gotonext;}}returntrue;next:continue;}returnfalse;}std::size_tstate_hash(){std::size_thash=0;for(intcolumn=0;column<7;++column){for(introw=5;row>=0;--row){hash=hash*3+static_cast<std::underlying_type_t<Color>>(grid[column][row]);}}returnhash;}};intmain(intargc,charconst**argv){charturn;std::cin>>turn;Boardboard{};try{switch(turn){while(true){case'f':{intmove=board.get_best_move();std::cout<<move<<std::endl;board.drop(move);[[fallthrough]];}case's':{intmove;std::cin>>move;board.drop(move);}}}}catch(std::exceptionconstex){std::cerr<<ex.what()<<std::endl;}}
entry #13
written by razetime submitted at 1 like
guesses
Amanda (by LyricLy)
Cow Bandit (by luatic)
Cow Bandit (by JJRubes)
LyricLy (by kimapr)
Olivia (by jetison333)
Olivia (by Amanda)
Olivia (by vspf)
luatic (by Olivia)
moshikoi (by yui)
razetime (by taswelll)
soup girl (by Cow Bandit)
comments 0
post a comment
connectfork.swfUnicode text, UTF-8 text, with CRLF line terminators
defstripList(lst):return[xforxinlstifnotxisNone]defendState():forx,colinenumerate(board):fory,spaceinenumerate(col):ifspace!=0:if(x+3<len(board)andspace==board[x+1][y]==board[x+2][y]==board[x+3][y]):returnspaceif(y+3<len(board[0])andspace==board[x][y+1]==board[x][y+2]==board[x][y+3]):returnspaceif(x+3<len(board)andy+3<len(board[0])andspace==board[x+1][y+1]==board[x+2][y+2]==board[x+3][y+3]):returnspaceif(x+3<len(board)andy-3>=0andspace==board[x+1][y-1]==board[x+2][y-2]==board[x+3][y-3]):returnspacereturn0defupdateBoard(move,player):moveStack.append(move)ifplayer==max:board[move][board[move].index(0)]=1else:board[move][board[move].index(0)]=-1defundo():move=moveStack.pop()if0inboard[move]:board[move][board[move].index(0)-1]=0else:board[move][-1]=0defcheck(arr):return0inarrand((1inarr)^(-1inarr))defevaluate4(arr):if1inarr:return10**(arr.count(1)-1)return-(10**(arr.count(-1)-1))defevaluateBoard():if(winner:=endState())!=0:returnwinner*100000total=0forx,colinenumerate(board):fory,spaceinenumerate(col):if(x+3<len(board)):right=[space,board[x+1][y],board[x+2][y],board[x+3][y]]ifcheck(right):total+=evaluate4(right)if(y+3<len(board[0])):up=[space,board[x][y+1],board[x][y+2],board[x][y+3]]ifcheck(up):total+=evaluate4(up)if(x+3<len(board)andy+3<len(board[0])):upright=[space,board[x+1][y+1],board[x+2][y+2],board[x+3][y+3]]ifcheck(upright):total+=evaluate4(upright)if(x+3<len(board)andy-3>=0):downright=[space,board[x+1][y-1],board[x+2][y-2],board[x+3][y-3]]ifcheck(downright):total+=evaluate4(downright)returntotaldefevaluateMove(move,player,depth=0):globalboardifnot0inboard[move]:returnNoneupdateBoard(move,minifplayer==maxelsemax)if(winner:=endState())!=0:returnVal=winner*100000elifdepth>4:#tune this if it takes to long/shortreturnVal=evaluateBoard()else:moves=[evaluateMove(x,minifplayer==maxelsemax,depth+1)forxinrange(7)]ifall(moveisNoneformoveinmoves):returnVal=Noneelse:returnVal=player(stripList(moves))undo()returnreturnValdefmove(player):moves=[evaluateMove(x,minifplayer==maxelsemax)forxinrange(7)]choosenMove=moves.index(player(stripList(moves)))updateBoard(choosenMove,player)returnchoosenMoveboard=[[0for_inrange(6)]for_inrange(7)]moveStack=[]side=input()player=maxifside=="f":player=minprint(move(player)+1)whileendState()==0:updateBoard(int(input())-1,minifplayer==maxelsemax)print(move(player)+1)
post a comment