Tässä on Javalla koodattu Simonin kaltainen peli, joka vaikeutuu joka kierroksella pelaajan onnistuttua. Mikäli pelaaja häviää peli alkaa taas helpoimmasta sarjasta.
Simon on 1970-luvulla Ralp H. Baerin ja Howard J. Morrisonin kehittämä elektroniikkapeli, jossa täytyy muistaa värien oikea sarja. Peli perustuu aikaisempaan Touch Me-peliin, joka oli Atari tuottama.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.ArrayList; import java.util.Random; public class Simon implements ActionListener { JFrame kehys; JButton[] nappaimet = new JButton[4]; JLabel teksti; JPanel paneeli; Font fontti = new Font("Arial",Font.BOLD,30); ArrayList<Integer> varit = new ArrayList<>(); Random sattuma = new Random(); int maara = 4; int indeksi = 0; boolean onkoAlkanut = false; boolean onkoVoitto = true; public void ArvoVarit(){ int vari = 0; int vanhaVari = 0; //Arvotaan kyseisen kierroksen värit. for (int i = 0; i < maara; i++){ //Arvotaan seuraava väri, joka ei saa olla sama kuin edellinen. do { vari = sattuma.nextInt(4); } while (vari == vanhaVari); varit.add(vari); vanhaVari = vari; } onkoVoitto = true; ajastin.start(); } Timer ajastin = new Timer(750,new ActionListener(){ public void actionPerformed(ActionEvent e){ if (!onkoAlkanut && onkoVoitto){ //Näytetään kierroksen värit. for (int i = 0; i < 4; i++){ nappaimet[i].setEnabled(false); } //Näytetään väri. if (indeksi < maara){ switch (varit.get(indeksi++)){ case 0: nappaimet[0].setBackground(Color.RED); nappaimet[1].setBackground(Color.WHITE); nappaimet[2].setBackground(Color.WHITE); nappaimet[3].setBackground(Color.WHITE); break; case 1: nappaimet[0].setBackground(Color.WHITE); nappaimet[1].setBackground(Color.YELLOW); nappaimet[2].setBackground(Color.WHITE); nappaimet[3].setBackground(Color.WHITE); break; case 2: nappaimet[0].setBackground(Color.WHITE); nappaimet[1].setBackground(Color.WHITE); nappaimet[2].setBackground(Color.GREEN); nappaimet[3].setBackground(Color.WHITE); break; case 3: nappaimet[0].setBackground(Color.WHITE); nappaimet[1].setBackground(Color.WHITE); nappaimet[2].setBackground(Color.WHITE); nappaimet[3].setBackground(Color.BLUE); break; } } else if (indeksi ==maara){ teksti.setText("Oletko valmis?"); indeksi++; } else if (indeksi > maara){ teksti.setText("Pelaa"); onkoAlkanut = true; nappaimet[0].setBackground(Color.WHITE); nappaimet[1].setBackground(Color.WHITE); nappaimet[2].setBackground(Color.WHITE); nappaimet[3].setBackground(Color.WHITE); indeksi = 0; for (int i = 0; i < 4; i++){ nappaimet[i].setEnabled(true); } } } } }); public void Tarkista(int ind){ //Tarkistetaan, onko väri oikein ja tarkistetaan voitto. if (!(ind == varit.get(indeksi++))){ onkoAlkanut = false; onkoVoitto = false; teksti.setText("Parempi onni ensi kerralla!"); maara = 4; } if (indeksi >= maara && onkoVoitto && onkoAlkanut){ //Aloitetaan seuraava, vaikeampi kierros. varit.clear(); onkoAlkanut = false; onkoVoitto = false; maara++; teksti.setText("Onneksi olkoon!"); } } Simon(){ //Määritellään kehys. kehys = new JFrame("Simon"); kehys.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); kehys.setSize(450,500); teksti = new JLabel("Paina näppäintä"); kehys.setLayout(null); //Määritellään tekstilappu. teksti.setFont(fontti); teksti.setBounds(0,50,300,50); //Määritellään näppäimet. paneeli = new JPanel(); paneeli.setBounds(0,100,400,350); paneeli.setLayout(new GridLayout(2,2)); for (int i = 0; i < 4; i++){ nappaimet[i] = new JButton("Pelaa"); nappaimet[i].addActionListener(this); paneeli.add(nappaimet[i]); nappaimet[i].setFocusable(false); } //Lisätään kontrollit kehykseen. kehys.add(teksti); kehys.add(paneeli); kehys.setVisible(true); } public static void main(String[] args){ final Simon simon = new Simon(); } @Override public void actionPerformed(ActionEvent e){ for (int i = 0; i < 4; i++){ if (e.getSource() == nappaimet[i]){ //Ensin arvotaan värit, sitten alkaa pelaajan vuoro. if (!onkoAlkanut){ indeksi = 0; ArvoVarit(); } else { Tarkista(i); } } } } }
koodaaja kirjoitti:
Tässä on Javalla koodattu Simonin kaltainen peli, joka vaikeutuu joka kierroksella pelaajan onnistuttua. Mikäli pelaaja häviää peli alkaa taas helpoimmasta sarjasta.
Olisi ehkä kivempi, jos käyttäisit värillisiä nappeja koko ajan niin väriä oikeasti voisi käyttää apuna järjestyksen muistamisessa. Samoin voisi olla kiva idea sijoittaa napit ympyrälle ja antaa väreille omat sektorinsa siitä. Ehkä helpoin parannus käyttöliittymään kuitenkin olisi sijoittaa se keskelle ikkunaa. Nyt kaikki on ihan vasemmassa reunassa ja oikealle jää tyhjää tilaa.
Hieno peli! Tässa on toteutus, kuinka Java -ohjelman saa toimimaan Grafiikkaliittymässä! Tämmöistä olen joskus haaveillut, mutta ei ole vielä ennen tullut vastaan. Tähän asti on pitänyt tehdä inputit ja outputit command prompt -ikkunan kautta. Nyt avautui uusi pelikenttä! Appletit toimivat joskus web-sivuilla, mutta enää ne ei toimi.
Jotain tämän tyylistä siis meinasin. Nappien toiminta helppo toteuttaa itse perus matematiikkaa apuna käyttäen. Tuohon keskelle meinasin laittaa pistelaskurin ja pelin viestit.
Päätinpä tehdä tästä sitten mobiiliversion. Alla kehitysversio, mistä puuttuu vielä ainakin ärsyttävät äänet mitkä esikuvassaan oli. Jos haluaa kokeilla ja verrata Java version käyttöliittymää, niin täältä voi ladata lähdekoodin ja binäärit useimmille käyttöjärjestelmille.
needs nk/gui \ Game states 0 constant START 1 constant READY 2 constant PLAY 3 constant END START var, game-state 0 2 n:PI n:* 4 n:/ dup >r 2 a:close constant PIE1 r@ dup 2 n:* 2 a:close constant PIE2 r@ 2 n:* dup r@ n:+ 2 a:close constant PIE3 r@ 3 n:* dup r> n:+ 2 a:close constant PIE4 [ @PIE1, @PIE2, @PIE3, @PIE4 ] constant SECTORS var score null var, highlight var seq-count var sequence var counter var anim-task-id with: nk 48 font:system font:new "font1" font:atlas! drop : new-win { name: "main", wide: 640, high: 480, bg: "white", title: "NOT Simon" } win ; : draw-circle \ [x y] r n c -- >r >r >r ( r@ n:- ) a:map a:open r> 2 n:* dup 4 a:close r> r> stroke-circle ; : draw-filled-circle \ [x y] r c -- >r >r ( r@ n:- ) a:map a:open r> 2 n:* dup 4 a:close r> fill-circle ; : angle? \ pta2 pta1 -- radians ( n:- n:neg ) a:2map a:open swap n:atan2 dup 0 n:< if 2 n:PI n:* swap n:+ then ; : distance? \ pta2 pta1 -- distance ( n:- n:sqr ) a:2map a:open n:+ n:sqrt ; : center-pt \ -- center-pt win-content-bounds rect-center nip ; : redraw null do ; : draw-pie center-pt 200 PIE1 "blue" fill-arc center-pt 200 PIE2 "red" fill-arc center-pt 200 PIE3 "yellow" fill-arc center-pt 200 PIE4 "green" fill-arc ; : draw-center center-pt x>pt 80 "white" draw-filled-circle center-pt x>pt 80 8 "black" draw-circle game-state @ START n:= game-state @ READY n:= or if win-content-bounds 0 0 game-state @ START n:= if "PLAY" else "READY" then dup >r measure swap 4 a:close center-rect r> "font1" "white" "black" draw-text else win-content-bounds 0 0 score @ "%04d" s:strfmt dup >r measure swap 4 a:close center-rect r> "font1" "white" game-state @ END n:= if "red" else "black" then draw-text then ; : mouse-clicked? \ -- T 0 win-content-bounds 0 clicked? ; : sector? \ angle distance -- n | null [ ( 2dup dup 200 n:> not swap 80 n:> and swap PIE1 a:open n:between and ), ( 2drop 0 ), ( 2dup dup 200 n:> not swap 80 n:> and swap PIE2 a:open n:between and ), ( 2drop 1 ), ( 2dup dup 200 n:> not swap 80 n:> and swap PIE3 a:open n:between and ), ( 2drop 2 ), ( 2dup dup 200 n:> not swap 80 n:> and swap PIE4 a:open n:between and ), ( 2drop 3 ), ( 2drop null ) ] a:when ; : init-game 0 score ! null highlight ! 4 seq-count ! 0 counter ! a:new ( rand-pcg 4 n:mod a:push ) seq-count @ times sequence ! READY game-state ! redraw ; : next-level null highlight ! 1 seq-count n:+! 0 counter ! a:new ( rand-pcg 4 n:mod a:push ) seq-count @ times sequence ! READY game-state ! redraw ; : handle-highlight highlight @ null? not if >r center-pt 200 SECTORS r> caseof 8 "black" stroke-arc else drop then ; : handle-mouse center-pt x>pt mouse-pos 2 a:close 2dup angle? 3rev distance? dup >r sector? null? not if game-state @ PLAY n:= if >r center-pt 200 SECTORS r@ caseof 0 down? if 8 else 4 then "black" stroke-arc mouse-clicked? if sequence @ counter @ a:@ nip r> n:= if score @ n:1+ 10000 n:mod score ! 1 counter n:+! counter @ seq-count @ n:< not if next-level anim-task-id @ t:notify then else END game-state ! then else rdrop then then else drop then r> 80 n:> not game-state @ START n:= game-state @ END n:= or and if center-pt x>pt 80 0 down? if 24 else 16 then "black" draw-circle mouse-clicked? if game-state @ END n:= if START game-state ! else init-game anim-task-id @ t:notify then then then ; : my-render { bg: "white", flags: [ @WINDOW_NO_SCROLLBAR ] } begin draw-pie [ ' handle-mouse , ' handle-highlight , ' handle-mouse , ' handle-mouse ] game-state @ case draw-center end ; : animate \ m -- "sector" m:@ nip highlight ! ; : anim-task repeat -1 sleep 0.5 sleep sequence @ ( 0.5 sleep m:new swap "sector" m:_! "cb" ' animate m:! do 0.5 sleep m:new "sector" null m:! "cb" ' animate m:! do ) a:each! drop 1 sleep ( PLAY game-state ! ) do again ; : app:main ' anim-task t:task anim-task-id ! new-win ' my-render -1 render-loop ;
Aihe on jo aika vanha, joten et voi enää vastata siihen.