邊打游戲邊學(xué)編程,是一種怎樣的體驗(yàn)?
前言
hello,大家好,我是bigsai,好久不見(jiàn),甚是想念!今天給大家介紹一個(gè)邊玩游戲邊學(xué)編程的網(wǎng)站。
在日常生活中,很多人喜歡玩游戲,因?yàn)橛螒蛑杏兄鴮?duì)抗博弈、控制的喜悅,用靈魂指法完成一波靚麗的操作。
但實(shí)際上,你的按鍵都是對(duì)應(yīng)代碼中一個(gè)個(gè)方法函數(shù)去執(zhí)行操作,并且界面做到一個(gè)圖形變化渲染讓你感覺(jué)你控制的是這個(gè)圖形界面,所以我一直非常佩服做游戲開(kāi)發(fā)的,感覺(jué)他們真的非常diao。
我們對(duì)代碼并沒(méi)有半點(diǎn)興趣因?yàn)閷?xiě)代碼的過(guò)程枯燥無(wú)趣,完全需要腦子去抽象出一個(gè)頁(yè)面、執(zhí)行邏輯,出錯(cuò)的時(shí)候有很簡(jiǎn)單的找了半天…… 輸出、debug各種方式去找問(wèn)題。
對(duì)于咱們這種懶人來(lái)說(shuō),想要鍛煉自己編程能力、算法真的是進(jìn)入一種畏難的無(wú)限死循環(huán),希望要么簡(jiǎn)單點(diǎn)、要么有趣點(diǎn),寫(xiě)的東西最好也能像有些開(kāi)發(fā)那樣看得見(jiàn),摸得著,學(xué)習(xí)別那么難。
這不,今天就發(fā)現(xiàn)了一個(gè)非常適合初、中級(jí)學(xué)者鍛煉自己編程的網(wǎng)站:codingame—一個(gè)邊玩游戲邊學(xué)編程的網(wǎng)站!
網(wǎng)站主頁(yè)為:https://www.codingame.com/start
網(wǎng)站介紹
我們?cè)趯W(xué)習(xí)技術(shù)、學(xué)習(xí)算法的時(shí)候,都喜歡看一些圖將抽象內(nèi)容具體化,甚至是如果有一些動(dòng)圖如果能夠模擬一下程序執(zhí)行邏輯之類(lèi)的那就更受歡迎了,但是往往這類(lèi)內(nèi)容涉及到的底層非常多,并且優(yōu)質(zhì)的內(nèi)容非常稀疏,但我今天推薦的這個(gè)網(wǎng)站真的是挺讓人驚喜的,網(wǎng)站進(jìn)入的第一感覺(jué)就是:臥槽,這是小霸王嘛? 啥玩意啊。
一些小游戲動(dòng)畫(huà)切換背景,看著codingame這個(gè)url你絲毫不會(huì)想到這個(gè)網(wǎng)站跟編程有啥任何關(guān)系,只會(huì)想到:
- 這到底是個(gè)啥?
- 谷歌翻譯一下看看……
注冊(cè)個(gè)賬號(hào)登錄之后才能顯示更多的內(nèi)容,仔細(xì)看下背景右側(cè)還是有一些代碼的,還是有一些非常神秘的感覺(jué)。
登錄之后,左上角的practice可以進(jìn)行一些練習(xí),頁(yè)面會(huì)有各種難度的游戲問(wèn)題,這些問(wèn)題都有一個(gè)小的游戲背景、規(guī)則、考察點(diǎn)等待你去完成,比如easy難度的大部分都是字符串、哈希、循環(huán)控制這類(lèi)問(wèn)題,而mid難度的考察點(diǎn)更廣泛比如很多二分查找、bfs、圖論等等,如果英文不好可以借助翻譯中英對(duì)比著看(狗頭??舉手),對(duì)于hard難度的有興趣可以自行挑戰(zhàn)。
對(duì)于這里面的問(wèn)題,有的是文本形式的,但是更多的是小游戲方式有動(dòng)畫(huà)更加直觀。
還有一個(gè)非常重要的是,它支持多種編程語(yǔ)言,不管你是那種主流語(yǔ)言的愛(ài)好者,都可以暢想邊玩游戲邊學(xué)編程的快樂(lè)。
easy初體驗(yàn):ASCII的藝術(shù)
這里和大家一起體驗(yàn)一下easy題怎么玩,我首先點(diǎn)進(jìn)去的是一個(gè)叫ASCII Art的題.
地址為:https://www.codingame.com/ide/puzzle/ascii-art
剛進(jìn)來(lái)就是一種黑色科技感十足,讀完題可能有些小伙伴很懵逼,這是啥玩意,這個(gè)程序又跟我們平常見(jiàn)得有點(diǎn)不一樣,不需要像力扣那樣完成整個(gè)方法,也不是和acm那種提交整個(gè)可執(zhí)行代碼提交,這個(gè)程序它會(huì)事先聲明好一些內(nèi)容你只需要在它提示的地方寫(xiě)對(duì)應(yīng)邏輯的代碼就可以了,并且所有的結(jié)果要打印出來(lái)。
但是細(xì)心的小伙伴會(huì)發(fā)現(xiàn)這個(gè)其實(shí)就是和我們?nèi)粘5乃㈩}很像很像,不就換個(gè)樣子嘛,沒(méi)啥不一樣的。
而這題的題意也很簡(jiǎn)單,我口述一下(可能不標(biāo)準(zhǔn)):
在機(jī)場(chǎng)你經(jīng)??吹竭@個(gè)牛pi的顯示屏:(圖片)
你有沒(méi)有問(wèn)過(guò)自己,在一個(gè)好的舊終端上怎么顯示這個(gè)數(shù)字?(我怎么會(huì)難為我自己呢),我們有:用ASCII藝術(shù)。
ASCII 藝術(shù)允許您使用字符來(lái)表示。準(zhǔn)確地說(shuō),在我們的例子中,這些形式是詞。例如,單詞“MANHATTAN”可以在 ASCII 藝術(shù)中顯示如下:
這個(gè)就有點(diǎn)似曾相識(shí)了,我也曾打印過(guò)大的0-9……
在看輸入輸出和其他要求
輸入
第 1 行:寬度L以 ASCII 藝術(shù)表示的字母。所有字母的寬度相同。
第 2 行:高度H以 ASCII 藝術(shù)表示的字母。所有字母的高度相同。
第 3行:待輸出的文本T,有n個(gè)ASCII字符組成。
后面幾行:字符串 ABCDEFGHIJKLMNOPQRSTUVWXYZ? 以 ASCII 藝術(shù)字(輸出到屏幕結(jié)果)表示。
輸出
文本 T在 ASCII 藝術(shù)中。
字符 a 到 z 在 ASCII 藝術(shù)中顯示為大寫(xiě)的等效字符。
不在區(qū)間 [az] 或 [AZ] 中的字符將在 ASCII 藝術(shù)中顯示為問(wèn)號(hào)。
問(wèn)題分析:
這雖然是個(gè)簡(jiǎn)單的問(wèn)題,但是怎么分析呢?
對(duì)于給定的寬度L,和高度H,其實(shí)就是限定了每個(gè)字符在控制臺(tái)的大小,這個(gè)如何理解呢,舉個(gè)例子你就能明白。對(duì)于0來(lái)說(shuō),不同寬高的0可能長(zhǎng)得樣子不一樣滴:
- # # # # # # # # # #
- # # # # # #
- # # # # # # #
- # # # #
- # # # # # # #
- 3*3 3*5 4*5
- 圓潤(rùn)型 瘦長(zhǎng)型 標(biāo)準(zhǔn)型
其實(shí)也就是限定寬高每個(gè)字符你可以迅速鎖定它的位置,存儲(chǔ)方面不用多想肯定是個(gè)二維的存儲(chǔ)(多個(gè)一維或者二維)。
在輸出的時(shí)候,根據(jù)字符計(jì)算 對(duì)應(yīng)的位置,對(duì)應(yīng)輸出就可以了,考慮到一些小白玩家還是可能不太明白,我貼上自己的????代碼,僅供參考:
- import java.util.*;
- import java.io.*;
- import java.math.*;
- /**
- * Auto-generated code below aims at helping you parse
- * the standard input according to the problem statement.
- **/
- class Solution {
- public static void main(String args[]) {
- Scanner in = new Scanner(System.in);
- int L = in.nextInt();//寬
- int H = in.nextInt();//高
- char ch[][]=new char[H][L];
- if (in.hasNextLine()) {
- in.nextLine();
- }
- String T = in.nextLine().toUpperCase();
- for (int i = 0; i < H; i++) {
- String ROW = in.nextLine();//輸入每一行
- ch[i]=ROW.toCharArray();//賦值給對(duì)應(yīng)行
- }
- char value[][]=new char[H][T.length()*L];
- for(int i=0;i<T.length();i++){
- char temp=T.charAt(i);
- int index=temp-'A';
- if(index<0||index>26)
- index=26;//不是字母統(tǒng)統(tǒng)問(wèn)號(hào) ???
- for(int j=0;j<H;j++){
- for(int q=0;q<L;q++)
- {
- value[j][q+i*L]=ch[j][q+L*index];//賦值給待輸出結(jié)果
- }
- }
- }
- for(char tem[]:value){
- for(char temp:tem){
- System.out.print(temp);
- }
- System.out.println();
- }
- // Write an answer using System.out.println()
- // To debug: System.err.println("Debug messages...");
- //System.out.println("answer");
- }
- }
執(zhí)行過(guò)程:
測(cè)試完提交即可。
mid初體驗(yàn)二分
看完一個(gè)easy題,你可能覺(jué)得好像也沒(méi)啥哈,那行,咱們一起看個(gè)經(jīng)典的mid題:
鏈接為:https://www.codingame.com/ide/puzzle/shadows-of-the-knight-episode-1
這個(gè)題具體要求大家可以自行到上面看看,但是大概的意思就是:
告訴你你在的區(qū)域長(zhǎng)寬,告訴你你的初始點(diǎn)。
你的目標(biāo)是最終走到某個(gè)終點(diǎn),不告訴你具體坐標(biāo),只告訴你目標(biāo)點(diǎn)在你當(dāng)前點(diǎn)的方位(有八個(gè)方向)。你需要在N步之內(nèi)走到目標(biāo)節(jié)點(diǎn)位置上,每走一輪你都要輸出你當(dāng)前點(diǎn)的位置。
看到這個(gè)問(wèn)題還沒(méi)讀太懂的時(shí)候,上去就寫(xiě)了個(gè)每次只走一步的代碼,結(jié)果遇到一個(gè)非常長(zhǎng)的地圖結(jié)構(gòu)那就GG了。
后來(lái)想了一下,告訴方位我們可以每次進(jìn)行二分查找,并且壓縮所在區(qū)域的位置啊,也就是
遇到所有U方位的:說(shuō)明地圖最底部在這個(gè)點(diǎn)之上
遇到所有D方位的:說(shuō)明地圖最頂部在這個(gè)點(diǎn)之下
遇到所有L方位的:說(shuō)明地圖最右側(cè)在這個(gè)點(diǎn)左面
遇到所有R方位的:說(shuō)明地圖最左部在這個(gè)點(diǎn)有點(diǎn)
通過(guò)使用二分,將以前的O(n)時(shí)間復(fù)雜度降到O(logn)級(jí)別,基本上可以找到所有點(diǎn)了。
個(gè)人的代碼可以給大家伙一個(gè)小參考:
- import java.util.*;
- import java.io.*;
- import java.math.*;
- /**
- * Auto-generated code below aims at helping you parse
- * the standard input according to the problem statement.
- **/
- class Player {
- public static void main(String args[]) {
- Scanner in = new Scanner(System.in);
- int W = in.nextInt(); // width of the building.
- int H = in.nextInt(); // height of the building.
- int N = in.nextInt(); // maximum number of turns before game over.
- int X0 = in.nextInt();
- int Y0 = in.nextInt();
- int u=0,d=H,l=0,r=W;
- // game loop
- while (true) {
- String bombDir = in.next(); // the direction of the bombs from batman's current location (U, UR, R, DR, D, DL, L or UL)
- // Write an action using System.out.println()
- // To debug: System.err.println("Debug messages...");
- if(bombDir.contains("U")){
- d=Y0;
- Y0=((u+Y0)/2);
- }
- if(bombDir.contains("D")){
- u=Y0+1;
- Y0=((d+Y0)/2);
- }
- if(bombDir.contains("L")){
- r=X0;
- X0=((l+X0)/2);
- }
- if(bombDir.contains("R")){
- l=X0;
- X0=((r+X0)/2);
- }
- // the location of the next window Batman should jump to.
- System.out.println(X0+" "+Y0);
- }
- }
- }
查看測(cè)試案例結(jié)果為:
當(dāng)然,對(duì)于每一個(gè)測(cè)試案例,你可以滾動(dòng)滑看其中的測(cè)試中間每一輪對(duì)應(yīng)的動(dòng)畫(huà),還是相當(dāng)nice的。
這樣自己寫(xiě)的代碼能夠可視化的看到每一步驟運(yùn)行在圖像上的結(jié)果,就像打怪升級(jí)一樣,有點(diǎn)意思。
總結(jié)
對(duì)于這么一個(gè)網(wǎng)站,對(duì)初學(xué)者編程興趣的激發(fā)還是挺友好的,推薦三兩隊(duì)友一起打怪升級(jí),也可舍友相互比拼,把這個(gè)題丟到寢室群里讓大伙一塊看看,看誰(shuí)先做對(duì)。
當(dāng)然網(wǎng)站內(nèi)容比較豐富這里就不一一列舉了,大家有興趣的可以自行體驗(yàn),在編程領(lǐng)域這種網(wǎng)站其實(shí)相對(duì)還是非常稀疏的。
不過(guò)任何一個(gè)工具都要挑著選著用,可以找一些有挑戰(zhàn)但自己可以接受的問(wèn)題去嘗試。玩玩體驗(yàn)一下還是挺有趣的!
邊玩游戲,邊學(xué)編程的體驗(yàn)很nice,就是讀題有點(diǎn)費(fèi)勁!