Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Java: Simonin kaltainen peli

koodaaja [14.06.2022 15:00:26]

#

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);
                }


             }

      }

   }



}

jalski [14.06.2022 19:20:40]

#

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.

TapaniS [15.06.2022 11:35:11]

#

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.

jalski [15.06.2022 23:09:20]

#

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.

jalski [16.06.2022 18:58:38]

#

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 ;

Vastaus

Muista lukea kirjoitusohjeet.
Tietoa sivustosta